All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
From: Gabriele Paoloni @ 2016-11-09 16:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161109113955.GD10219@e106497-lin.cambridge.arm.com>

Hi Liviu

Thanks for reviewing

> -----Original Message-----
> From: liviu.dudau at arm.com [mailto:liviu.dudau at arm.com]
> Sent: 09 November 2016 11:40
> To: Yuanzhichang
> Cc: catalin.marinas at arm.com; will.deacon at arm.com; robh+dt at kernel.org;
> bhelgaas at google.com; mark.rutland at arm.com; olof at lixom.net;
> arnd at arndb.de; linux-arm-kernel at lists.infradead.org;
> lorenzo.pieralisi at arm.com; linux-kernel at vger.kernel.org; Linuxarm;
> devicetree at vger.kernel.org; linux-pci at vger.kernel.org; linux-
> serial at vger.kernel.org; minyard at acm.org; benh at kernel.crashing.org;
> zourongrong at gmail.com; John Garry; Gabriele Paoloni;
> zhichang.yuan02 at gmail.com; kantyzc at 163.com; xuwei (O)
> Subject: Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for
> special ISA
> 
> On Tue, Nov 08, 2016 at 11:47:08AM +0800, zhichang.yuan wrote:
> > This patch solves two issues:
> > 1) parse and get the right I/O range from DTS node whose parent does
> not
> > define the corresponding ranges property;
> >
> > There are some special ISA/LPC devices that work on a specific I/O
> range where
> > it is not correct to specify a ranges property in DTS parent node as
> cpu
> > addresses translated from DTS node are only for memory space on some
> > architectures, such as Arm64. Without the parent 'ranges' property,
> current
> > of_translate_address() return an error.
> > Here we add a fixup function, of_get_isa_indirect_io(). During the OF
> address
> > translation, this fixup will be called to check the 'reg' address to
> be
> > translating is for those sepcial ISA/LPC devices and get the I/O
> range
> > directly from the 'reg' property.
> >
> > 2) eliminate the I/O range conflict risk with PCI/PCIE leagecy I/O
> device;
> >
> > The current __of_address_to_resource() always translates the I/O
> range to PIO.
> > But this processing is not suitable for our ISA/LPC devices whose I/O
> range is
> > not cpu address(Arnd had stressed this in his comments on V2,V3
> patch-set).
> > Here, we bypass the mapping between cpu address and PIO for the
> special
> > ISA/LPC devices. But to drive these ISA/LPC devices, a I/O port
> address below
> > PCIBIOS_MIN_IO is needed by in*/out*(). Which means there is conflict
> risk
> > between I/O range of [0, PCIBIOS_MIN_IO) and PCI/PCIE legacy I/O
> range of [0,
> > IO_SPACE_LIMIT).
> > To avoid the I/O conflict, this patch reserve the I/O range below
> > PCIBIOS_MIN_IO.
> >
> > Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > ---
> >  .../arm/hisilicon/hisilicon-low-pin-count.txt      | 31 ++++++++++++
> >  arch/arm64/include/asm/io.h                        |  6 +++
> >  arch/arm64/kernel/extio.c                          | 25 ++++++++++
> >  drivers/of/address.c                               | 56
> +++++++++++++++++++++-
> >  drivers/pci/pci.c                                  |  6 +--
> >  include/linux/of_address.h                         | 17 +++++++
> >  include/linux/pci.h                                |  8 ++++
> >  7 files changed, 145 insertions(+), 4 deletions(-)
> >  create mode 100644
> Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-
> count.txt
> >
> > diff --git
> a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-
> count.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-
> low-pin-count.txt
> > new file mode 100644
> > index 0000000..13c8ddd
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-
> pin-count.txt
> > @@ -0,0 +1,31 @@
> > +Hisilicon Hip06 low-pin-count device
> > +  Usually LPC controller is part of PCI host bridge, so the legacy
> ISA ports
> > +  locate on LPC bus can be accessed direclty. But some SoCs have
> independent
> > +  LPC controller, and access the legacy ports by triggering LPC I/O
> cycles.
> > +  Hisilicon Hip06 implements this LPC device.
> > +
> > +Required properties:
> > +- compatible: should be "hisilicon,low-pin-count"
> > +- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
> > +- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
> > +- reg: base memory range where the register set of this device is
> mapped.
> > +
> > +Note:
> > +  The node name before '@' must be "isa" to represent the binding
> stick to the
> > +  ISA/EISA binding specification.
> > +
> > +Example:
> > +
> > +isa at a01b0000 {
> > +	compatible = "hisilicom,low-pin-count";
> > +	#address-cells = <2>;
> > +	#size-cells = <1>;
> > +	reg = <0x0 0xa01b0000 0x0 0x1000>;
> > +
> > +	ipmi0: bt at e4 {
> > +		compatible = "ipmi-bt";
> > +		device_type = "ipmi";
> > +		reg = <0x01 0xe4 0x04>;
> > +		status = "disabled";
> > +	};
> > +};
> 
> 
> This documentation file needs to be part of the next patch. It has
> nothing to do with
> what you are trying to fix here.

Yes you're right...we'll move it to next one

> 
> 
> > diff --git a/arch/arm64/include/asm/io.h
> b/arch/arm64/include/asm/io.h
> > index 136735d..c26b7cc 100644
> > --- a/arch/arm64/include/asm/io.h
> > +++ b/arch/arm64/include/asm/io.h
> > @@ -175,6 +175,12 @@ static inline u64 __raw_readq(const volatile
> void __iomem *addr)
> >  #define outsl outsl
> >
> >  DECLARE_EXTIO(l, u32)
> > +
> > +#define indirect_io_enabled indirect_io_enabled
> > +extern bool indirect_io_enabled(void);
> > +
> > +#define addr_is_indirect_io addr_is_indirect_io
> > +extern int addr_is_indirect_io(u64 taddr);
> >  #endif
> >
> >
> > diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
> > index 647b3fa..3d45fa8 100644
> > --- a/arch/arm64/kernel/extio.c
> > +++ b/arch/arm64/kernel/extio.c
> > @@ -19,6 +19,31 @@
> >
> >  struct extio_ops *arm64_extio_ops;
> >
> > +/**
> > + * indirect_io_enabled - check whether indirectIO is enabled.
> > + *	arm64_extio_ops will be set only when indirectIO mechanism had
> been
> > + *	initialized.
> > + *
> > + * Returns true when indirectIO is enabled.
> > + */
> > +bool indirect_io_enabled(void)
> > +{
> > +	return arm64_extio_ops ? true : false;
> > +}
> > +
> > +/**
> > + * addr_is_indirect_io - check whether the input taddr is for
> indirectIO.
> > + * @taddr: the io address to be checked.
> > + *
> > + * Returns 1 when taddr is in the range; otherwise return 0.
> > + */
> > +int addr_is_indirect_io(u64 taddr)
> > +{
> > +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end <
> taddr)
> 
> start >= taddr ?

Nope... if  (taddr < arm64_extio_ops->start || taddr > arm64_extio_ops->end)
then taddr is outside the range [start; end] and will return 0; otherwise
it will return 1...

> 
> > +		return 0;
> > +
> > +	return 1;
> > +}
> >
> >  BUILD_EXTIO(b, u8)
> >
> > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > index 02b2903..cc2a05d 100644
> > --- a/drivers/of/address.c
> > +++ b/drivers/of/address.c
> > @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct
> device_node *np)
> >  	return false;
> >  }
> >
> > +
> > +/*
> > + * of_isa_indirect_io - get the IO address from some isa reg
> property value.
> > + *	For some isa/lpc devices, no ranges property in ancestor node.
> > + *	The device addresses are described directly in their regs
> property.
> > + *	This fixup function will be called to get the IO address of
> isa/lpc
> > + *	devices when the normal of_translation failed.
> > + *
> > + * @parent:	points to the parent dts node;
> > + * @bus:		points to the of_bus which can be used to parse
> address;
> > + * @addr:	the address from reg property;
> > + * @na:		the address cell counter of @addr;
> > + * @presult:	store the address paresed from @addr;
> > + *
> > + * return 1 when successfully get the I/O address;
> > + * 0 will return for some failures.
> 
> Bah, you are returning a signed int, why 0 for failure? Return a
> negative value with
> error codes. Otherwise change the return value into a bool.

Yes we'll move to bool

> 
> > + */
> > +static int of_get_isa_indirect_io(struct device_node *parent,
> > +				struct of_bus *bus, __be32 *addr,
> > +				int na, u64 *presult)
> > +{
> > +	unsigned int flags;
> > +	unsigned int rlen;
> > +
> > +	/* whether support indirectIO */
> > +	if (!indirect_io_enabled())
> > +		return 0;
> > +
> > +	if (!of_bus_isa_match(parent))
> > +		return 0;
> > +
> > +	flags = bus->get_flags(addr);
> > +	if (!(flags & IORESOURCE_IO))
> > +		return 0;
> > +
> > +	/* there is ranges property, apply the normal translation
> directly. */
> 
> s/there is ranges/if we have a 'ranges'/

Thanks for spotting this

> 
> > +	if (of_get_property(parent, "ranges", &rlen))
> > +		return 0;
> > +
> > +	*presult = of_read_number(addr + 1, na - 1);
> > +	/* this fixup is only valid for specific I/O range. */
> > +	return addr_is_indirect_io(*presult);
> > +}
> > +
> >  static int of_translate_one(struct device_node *parent, struct
> of_bus *bus,
> >  			    struct of_bus *pbus, __be32 *addr,
> >  			    int na, int ns, int pna, const char *rprop)
> > @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct
> device_node *dev,
> >  			result = of_read_number(addr, na);
> >  			break;
> >  		}
> > +		/*
> > +		 * For indirectIO device which has no ranges property, get
> > +		 * the address from reg directly.
> > +		 */
> > +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> > +			pr_debug("isa indirectIO matched(%s)..addr =
> 0x%llx\n",
> > +				of_node_full_name(dev), result);
> > +			break;
> > +		}
> >
> >  		/* Get new parent bus and counts */
> >  		pbus = of_match_bus(parent);
> > @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct
> device_node *dev,
> >  	if (taddr == OF_BAD_ADDR)
> >  		return -EINVAL;
> >  	memset(r, 0, sizeof(struct resource));
> > -	if (flags & IORESOURCE_IO) {
> > +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
> >  		unsigned long port;
> > +
> >  		port = pci_address_to_pio(taddr);
> >  		if (port == (unsigned long)-1)
> >  			return -EINVAL;
> > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > index ba34907..1a08511 100644
> > --- a/drivers/pci/pci.c
> > +++ b/drivers/pci/pci.c
> > @@ -3263,7 +3263,7 @@ int __weak pci_register_io_range(phys_addr_t
> addr, resource_size_t size)
> >
> >  #ifdef PCI_IOBASE
> >  	struct io_range *range;
> > -	resource_size_t allocated_size = 0;
> > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> >
> >  	/* check if the range hasn't been previously recorded */
> >  	spin_lock(&io_range_lock);
> > @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned long
> pio)
> >
> >  #ifdef PCI_IOBASE
> >  	struct io_range *range;
> > -	resource_size_t allocated_size = 0;
> > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> 
> Have you checked that pci_pio_to_address still returns valid values
> after this? I know that
> you are trying to take into account PCIBIOS_MIN_IO limit when
> allocating reserving the IO ranges,
> but the values added in the io_range_list are still starting from zero,
> no from PCIBIOS_MIN_IO,

I think you're wrong here as in pci_address_to_pio we have:
+	resource_size_t offset = PCIBIOS_MIN_IO;

This should be enough to guarantee that the PIOs start at
PCIBIOS_MIN_IO...right?


> so the calculation of the address in this function could return
> negative values casted to pci_addr_t.
> 
> Maybe you want to adjust the range->start value in
> pci_register_io_range() as well to have it
> offset by PCIBIOS_MIN_IO as well.
> 
> Best regards,
> Liviu
> 
> >
> >  	if (pio > IO_SPACE_LIMIT)
> >  		return address;
> > @@ -3335,7 +3335,7 @@ unsigned long __weak
> pci_address_to_pio(phys_addr_t address)
> >  {
> >  #ifdef PCI_IOBASE
> >  	struct io_range *res;
> > -	resource_size_t offset = 0;
> > +	resource_size_t offset = PCIBIOS_MIN_IO;
> >  	unsigned long addr = -1;
> >
> >  	spin_lock(&io_range_lock);
> > diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> > index 3786473..deec469 100644
> > --- a/include/linux/of_address.h
> > +++ b/include/linux/of_address.h
> > @@ -24,6 +24,23 @@ struct of_pci_range {
> >  #define for_each_of_pci_range(parser, range) \
> >  	for (; of_pci_range_parser_one(parser, range);)
> >
> > +
> > +#ifndef indirect_io_enabled
> > +#define indirect_io_enabled indirect_io_enabled
> > +static inline bool indirect_io_enabled(void)
> > +{
> > +	return false;
> > +}
> > +#endif
> > +
> > +#ifndef addr_is_indirect_io
> > +#define addr_is_indirect_io addr_is_indirect_io
> > +static inline int addr_is_indirect_io(u64 taddr)
> > +{
> > +	return 0;
> > +}
> > +#endif
> > +
> >  /* Translate a DMA address from device space to CPU space */
> >  extern u64 of_translate_dma_address(struct device_node *dev,
> >  				    const __be32 *in_addr);
> > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > index 0e49f70..7f6bbb6 100644
> > --- a/include/linux/pci.h
> > +++ b/include/linux/pci.h
> > @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct
> pci_bus *bus)
> >  /* provide the legacy pci_dma_* API */
> >  #include <linux/pci-dma-compat.h>
> >
> > +/*
> > + * define this macro here to refrain from compilation error for some
> > + * platforms. Please keep this macro at the end of this header file.
> > + */
> > +#ifndef PCIBIOS_MIN_IO
> > +#define PCIBIOS_MIN_IO		0
> > +#endif
> > +
> >  #endif /* LINUX_PCI_H */
> > --
> > 1.9.1
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-pci"
> in
> > the body of a message to majordomo at vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> --
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ?\_(?)_/?

^ permalink raw reply

* RE: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
From: Gabriele Paoloni @ 2016-11-09 16:16 UTC (permalink / raw)
  To: liviu.dudau@arm.com, Yuanzhichang
  Cc: catalin.marinas@arm.com, will.deacon@arm.com, robh+dt@kernel.org,
	bhelgaas@google.com, mark.rutland@arm.com, olof@lixom.net,
	arnd@arndb.de, linux-arm-kernel@lists.infradead.org,
	lorenzo.pieralisi@arm.com, linux-kernel@vger.kernel.org, Linuxarm,
	devicetree@vger.kernel.org, linux-pci@vger.kernel.org,
	linux-serial@vger.kernel.org, minyard@acm.org, benh
In-Reply-To: <20161109113955.GD10219@e106497-lin.cambridge.arm.com>

Hi Liviu

Thanks for reviewing

> -----Original Message-----
> From: liviu.dudau@arm.com [mailto:liviu.dudau@arm.com]
> Sent: 09 November 2016 11:40
> To: Yuanzhichang
> Cc: catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> bhelgaas@google.com; mark.rutland@arm.com; olof@lixom.net;
> arnd@arndb.de; linux-arm-kernel@lists.infradead.org;
> lorenzo.pieralisi@arm.com; linux-kernel@vger.kernel.org; Linuxarm;
> devicetree@vger.kernel.org; linux-pci@vger.kernel.org; linux-
> serial@vger.kernel.org; minyard@acm.org; benh@kernel.crashing.org;
> zourongrong@gmail.com; John Garry; Gabriele Paoloni;
> zhichang.yuan02@gmail.com; kantyzc@163.com; xuwei (O)
> Subject: Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for
> special ISA
> 
> On Tue, Nov 08, 2016 at 11:47:08AM +0800, zhichang.yuan wrote:
> > This patch solves two issues:
> > 1) parse and get the right I/O range from DTS node whose parent does
> not
> > define the corresponding ranges property;
> >
> > There are some special ISA/LPC devices that work on a specific I/O
> range where
> > it is not correct to specify a ranges property in DTS parent node as
> cpu
> > addresses translated from DTS node are only for memory space on some
> > architectures, such as Arm64. Without the parent 'ranges' property,
> current
> > of_translate_address() return an error.
> > Here we add a fixup function, of_get_isa_indirect_io(). During the OF
> address
> > translation, this fixup will be called to check the 'reg' address to
> be
> > translating is for those sepcial ISA/LPC devices and get the I/O
> range
> > directly from the 'reg' property.
> >
> > 2) eliminate the I/O range conflict risk with PCI/PCIE leagecy I/O
> device;
> >
> > The current __of_address_to_resource() always translates the I/O
> range to PIO.
> > But this processing is not suitable for our ISA/LPC devices whose I/O
> range is
> > not cpu address(Arnd had stressed this in his comments on V2,V3
> patch-set).
> > Here, we bypass the mapping between cpu address and PIO for the
> special
> > ISA/LPC devices. But to drive these ISA/LPC devices, a I/O port
> address below
> > PCIBIOS_MIN_IO is needed by in*/out*(). Which means there is conflict
> risk
> > between I/O range of [0, PCIBIOS_MIN_IO) and PCI/PCIE legacy I/O
> range of [0,
> > IO_SPACE_LIMIT).
> > To avoid the I/O conflict, this patch reserve the I/O range below
> > PCIBIOS_MIN_IO.
> >
> > Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > ---
> >  .../arm/hisilicon/hisilicon-low-pin-count.txt      | 31 ++++++++++++
> >  arch/arm64/include/asm/io.h                        |  6 +++
> >  arch/arm64/kernel/extio.c                          | 25 ++++++++++
> >  drivers/of/address.c                               | 56
> +++++++++++++++++++++-
> >  drivers/pci/pci.c                                  |  6 +--
> >  include/linux/of_address.h                         | 17 +++++++
> >  include/linux/pci.h                                |  8 ++++
> >  7 files changed, 145 insertions(+), 4 deletions(-)
> >  create mode 100644
> Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-
> count.txt
> >
> > diff --git
> a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-
> count.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-
> low-pin-count.txt
> > new file mode 100644
> > index 0000000..13c8ddd
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-
> pin-count.txt
> > @@ -0,0 +1,31 @@
> > +Hisilicon Hip06 low-pin-count device
> > +  Usually LPC controller is part of PCI host bridge, so the legacy
> ISA ports
> > +  locate on LPC bus can be accessed direclty. But some SoCs have
> independent
> > +  LPC controller, and access the legacy ports by triggering LPC I/O
> cycles.
> > +  Hisilicon Hip06 implements this LPC device.
> > +
> > +Required properties:
> > +- compatible: should be "hisilicon,low-pin-count"
> > +- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
> > +- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
> > +- reg: base memory range where the register set of this device is
> mapped.
> > +
> > +Note:
> > +  The node name before '@' must be "isa" to represent the binding
> stick to the
> > +  ISA/EISA binding specification.
> > +
> > +Example:
> > +
> > +isa@a01b0000 {
> > +	compatible = "hisilicom,low-pin-count";
> > +	#address-cells = <2>;
> > +	#size-cells = <1>;
> > +	reg = <0x0 0xa01b0000 0x0 0x1000>;
> > +
> > +	ipmi0: bt@e4 {
> > +		compatible = "ipmi-bt";
> > +		device_type = "ipmi";
> > +		reg = <0x01 0xe4 0x04>;
> > +		status = "disabled";
> > +	};
> > +};
> 
> 
> This documentation file needs to be part of the next patch. It has
> nothing to do with
> what you are trying to fix here.

Yes you're right...we'll move it to next one

> 
> 
> > diff --git a/arch/arm64/include/asm/io.h
> b/arch/arm64/include/asm/io.h
> > index 136735d..c26b7cc 100644
> > --- a/arch/arm64/include/asm/io.h
> > +++ b/arch/arm64/include/asm/io.h
> > @@ -175,6 +175,12 @@ static inline u64 __raw_readq(const volatile
> void __iomem *addr)
> >  #define outsl outsl
> >
> >  DECLARE_EXTIO(l, u32)
> > +
> > +#define indirect_io_enabled indirect_io_enabled
> > +extern bool indirect_io_enabled(void);
> > +
> > +#define addr_is_indirect_io addr_is_indirect_io
> > +extern int addr_is_indirect_io(u64 taddr);
> >  #endif
> >
> >
> > diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
> > index 647b3fa..3d45fa8 100644
> > --- a/arch/arm64/kernel/extio.c
> > +++ b/arch/arm64/kernel/extio.c
> > @@ -19,6 +19,31 @@
> >
> >  struct extio_ops *arm64_extio_ops;
> >
> > +/**
> > + * indirect_io_enabled - check whether indirectIO is enabled.
> > + *	arm64_extio_ops will be set only when indirectIO mechanism had
> been
> > + *	initialized.
> > + *
> > + * Returns true when indirectIO is enabled.
> > + */
> > +bool indirect_io_enabled(void)
> > +{
> > +	return arm64_extio_ops ? true : false;
> > +}
> > +
> > +/**
> > + * addr_is_indirect_io - check whether the input taddr is for
> indirectIO.
> > + * @taddr: the io address to be checked.
> > + *
> > + * Returns 1 when taddr is in the range; otherwise return 0.
> > + */
> > +int addr_is_indirect_io(u64 taddr)
> > +{
> > +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end <
> taddr)
> 
> start >= taddr ?

Nope... if  (taddr < arm64_extio_ops->start || taddr > arm64_extio_ops->end)
then taddr is outside the range [start; end] and will return 0; otherwise
it will return 1...

> 
> > +		return 0;
> > +
> > +	return 1;
> > +}
> >
> >  BUILD_EXTIO(b, u8)
> >
> > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > index 02b2903..cc2a05d 100644
> > --- a/drivers/of/address.c
> > +++ b/drivers/of/address.c
> > @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct
> device_node *np)
> >  	return false;
> >  }
> >
> > +
> > +/*
> > + * of_isa_indirect_io - get the IO address from some isa reg
> property value.
> > + *	For some isa/lpc devices, no ranges property in ancestor node.
> > + *	The device addresses are described directly in their regs
> property.
> > + *	This fixup function will be called to get the IO address of
> isa/lpc
> > + *	devices when the normal of_translation failed.
> > + *
> > + * @parent:	points to the parent dts node;
> > + * @bus:		points to the of_bus which can be used to parse
> address;
> > + * @addr:	the address from reg property;
> > + * @na:		the address cell counter of @addr;
> > + * @presult:	store the address paresed from @addr;
> > + *
> > + * return 1 when successfully get the I/O address;
> > + * 0 will return for some failures.
> 
> Bah, you are returning a signed int, why 0 for failure? Return a
> negative value with
> error codes. Otherwise change the return value into a bool.

Yes we'll move to bool

> 
> > + */
> > +static int of_get_isa_indirect_io(struct device_node *parent,
> > +				struct of_bus *bus, __be32 *addr,
> > +				int na, u64 *presult)
> > +{
> > +	unsigned int flags;
> > +	unsigned int rlen;
> > +
> > +	/* whether support indirectIO */
> > +	if (!indirect_io_enabled())
> > +		return 0;
> > +
> > +	if (!of_bus_isa_match(parent))
> > +		return 0;
> > +
> > +	flags = bus->get_flags(addr);
> > +	if (!(flags & IORESOURCE_IO))
> > +		return 0;
> > +
> > +	/* there is ranges property, apply the normal translation
> directly. */
> 
> s/there is ranges/if we have a 'ranges'/

Thanks for spotting this

> 
> > +	if (of_get_property(parent, "ranges", &rlen))
> > +		return 0;
> > +
> > +	*presult = of_read_number(addr + 1, na - 1);
> > +	/* this fixup is only valid for specific I/O range. */
> > +	return addr_is_indirect_io(*presult);
> > +}
> > +
> >  static int of_translate_one(struct device_node *parent, struct
> of_bus *bus,
> >  			    struct of_bus *pbus, __be32 *addr,
> >  			    int na, int ns, int pna, const char *rprop)
> > @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct
> device_node *dev,
> >  			result = of_read_number(addr, na);
> >  			break;
> >  		}
> > +		/*
> > +		 * For indirectIO device which has no ranges property, get
> > +		 * the address from reg directly.
> > +		 */
> > +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> > +			pr_debug("isa indirectIO matched(%s)..addr =
> 0x%llx\n",
> > +				of_node_full_name(dev), result);
> > +			break;
> > +		}
> >
> >  		/* Get new parent bus and counts */
> >  		pbus = of_match_bus(parent);
> > @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct
> device_node *dev,
> >  	if (taddr == OF_BAD_ADDR)
> >  		return -EINVAL;
> >  	memset(r, 0, sizeof(struct resource));
> > -	if (flags & IORESOURCE_IO) {
> > +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
> >  		unsigned long port;
> > +
> >  		port = pci_address_to_pio(taddr);
> >  		if (port == (unsigned long)-1)
> >  			return -EINVAL;
> > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > index ba34907..1a08511 100644
> > --- a/drivers/pci/pci.c
> > +++ b/drivers/pci/pci.c
> > @@ -3263,7 +3263,7 @@ int __weak pci_register_io_range(phys_addr_t
> addr, resource_size_t size)
> >
> >  #ifdef PCI_IOBASE
> >  	struct io_range *range;
> > -	resource_size_t allocated_size = 0;
> > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> >
> >  	/* check if the range hasn't been previously recorded */
> >  	spin_lock(&io_range_lock);
> > @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned long
> pio)
> >
> >  #ifdef PCI_IOBASE
> >  	struct io_range *range;
> > -	resource_size_t allocated_size = 0;
> > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> 
> Have you checked that pci_pio_to_address still returns valid values
> after this? I know that
> you are trying to take into account PCIBIOS_MIN_IO limit when
> allocating reserving the IO ranges,
> but the values added in the io_range_list are still starting from zero,
> no from PCIBIOS_MIN_IO,

I think you're wrong here as in pci_address_to_pio we have:
+	resource_size_t offset = PCIBIOS_MIN_IO;

This should be enough to guarantee that the PIOs start at
PCIBIOS_MIN_IO...right?


> so the calculation of the address in this function could return
> negative values casted to pci_addr_t.
> 
> Maybe you want to adjust the range->start value in
> pci_register_io_range() as well to have it
> offset by PCIBIOS_MIN_IO as well.
> 
> Best regards,
> Liviu
> 
> >
> >  	if (pio > IO_SPACE_LIMIT)
> >  		return address;
> > @@ -3335,7 +3335,7 @@ unsigned long __weak
> pci_address_to_pio(phys_addr_t address)
> >  {
> >  #ifdef PCI_IOBASE
> >  	struct io_range *res;
> > -	resource_size_t offset = 0;
> > +	resource_size_t offset = PCIBIOS_MIN_IO;
> >  	unsigned long addr = -1;
> >
> >  	spin_lock(&io_range_lock);
> > diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> > index 3786473..deec469 100644
> > --- a/include/linux/of_address.h
> > +++ b/include/linux/of_address.h
> > @@ -24,6 +24,23 @@ struct of_pci_range {
> >  #define for_each_of_pci_range(parser, range) \
> >  	for (; of_pci_range_parser_one(parser, range);)
> >
> > +
> > +#ifndef indirect_io_enabled
> > +#define indirect_io_enabled indirect_io_enabled
> > +static inline bool indirect_io_enabled(void)
> > +{
> > +	return false;
> > +}
> > +#endif
> > +
> > +#ifndef addr_is_indirect_io
> > +#define addr_is_indirect_io addr_is_indirect_io
> > +static inline int addr_is_indirect_io(u64 taddr)
> > +{
> > +	return 0;
> > +}
> > +#endif
> > +
> >  /* Translate a DMA address from device space to CPU space */
> >  extern u64 of_translate_dma_address(struct device_node *dev,
> >  				    const __be32 *in_addr);
> > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > index 0e49f70..7f6bbb6 100644
> > --- a/include/linux/pci.h
> > +++ b/include/linux/pci.h
> > @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct
> pci_bus *bus)
> >  /* provide the legacy pci_dma_* API */
> >  #include <linux/pci-dma-compat.h>
> >
> > +/*
> > + * define this macro here to refrain from compilation error for some
> > + * platforms. Please keep this macro at the end of this header file.
> > + */
> > +#ifndef PCIBIOS_MIN_IO
> > +#define PCIBIOS_MIN_IO		0
> > +#endif
> > +
> >  #endif /* LINUX_PCI_H */
> > --
> > 1.9.1
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-pci"
> in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> --
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ¯\_(ツ)_/¯

^ permalink raw reply

* RE: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
From: Gabriele Paoloni @ 2016-11-09 16:16 UTC (permalink / raw)
  To: liviu.dudau@arm.com, Yuanzhichang
  Cc: catalin.marinas@arm.com, will.deacon@arm.com, robh+dt@kernel.org,
	bhelgaas@google.com, mark.rutland@arm.com, olof@lixom.net,
	arnd@arndb.de, linux-arm-kernel@lists.infradead.org,
	lorenzo.pieralisi@arm.com, linux-kernel@vger.kernel.org, Linuxarm,
	devicetree@vger.kernel.org, linux-pci@vger.kernel.org,
	linux-serial@vger.kernel.org, minyard@acm.org,
	benh@kernel.crashing.org, zourongrong@gmail.com, John Garry,
	zhichang.yuan02@gmail.com, kantyzc@163.com, xuwei (O)
In-Reply-To: <20161109113955.GD10219@e106497-lin.cambridge.arm.com>

SGkgTGl2aXUNCg0KVGhhbmtzIGZvciByZXZpZXdpbmcNCg0KPiAtLS0tLU9yaWdpbmFsIE1lc3Nh
Z2UtLS0tLQ0KPiBGcm9tOiBsaXZpdS5kdWRhdUBhcm0uY29tIFttYWlsdG86bGl2aXUuZHVkYXVA
YXJtLmNvbV0NCj4gU2VudDogMDkgTm92ZW1iZXIgMjAxNiAxMTo0MA0KPiBUbzogWXVhbnpoaWNo
YW5nDQo+IENjOiBjYXRhbGluLm1hcmluYXNAYXJtLmNvbTsgd2lsbC5kZWFjb25AYXJtLmNvbTsg
cm9iaCtkdEBrZXJuZWwub3JnOw0KPiBiaGVsZ2Fhc0Bnb29nbGUuY29tOyBtYXJrLnJ1dGxhbmRA
YXJtLmNvbTsgb2xvZkBsaXhvbS5uZXQ7DQo+IGFybmRAYXJuZGIuZGU7IGxpbnV4LWFybS1rZXJu
ZWxAbGlzdHMuaW5mcmFkZWFkLm9yZzsNCj4gbG9yZW56by5waWVyYWxpc2lAYXJtLmNvbTsgbGlu
dXgta2VybmVsQHZnZXIua2VybmVsLm9yZzsgTGludXhhcm07DQo+IGRldmljZXRyZWVAdmdlci5r
ZXJuZWwub3JnOyBsaW51eC1wY2lAdmdlci5rZXJuZWwub3JnOyBsaW51eC0NCj4gc2VyaWFsQHZn
ZXIua2VybmVsLm9yZzsgbWlueWFyZEBhY20ub3JnOyBiZW5oQGtlcm5lbC5jcmFzaGluZy5vcmc7
DQo+IHpvdXJvbmdyb25nQGdtYWlsLmNvbTsgSm9obiBHYXJyeTsgR2FicmllbGUgUGFvbG9uaTsN
Cj4gemhpY2hhbmcueXVhbjAyQGdtYWlsLmNvbTsga2FudHl6Y0AxNjMuY29tOyB4dXdlaSAoTykN
Cj4gU3ViamVjdDogUmU6IFtQQVRDSCBWNSAyLzNdIEFSTTY0IExQQzogQWRkIG1pc3NpbmcgcmFu
Z2UgZXhjZXB0aW9uIGZvcg0KPiBzcGVjaWFsIElTQQ0KPiANCj4gT24gVHVlLCBOb3YgMDgsIDIw
MTYgYXQgMTE6NDc6MDhBTSArMDgwMCwgemhpY2hhbmcueXVhbiB3cm90ZToNCj4gPiBUaGlzIHBh
dGNoIHNvbHZlcyB0d28gaXNzdWVzOg0KPiA+IDEpIHBhcnNlIGFuZCBnZXQgdGhlIHJpZ2h0IEkv
TyByYW5nZSBmcm9tIERUUyBub2RlIHdob3NlIHBhcmVudCBkb2VzDQo+IG5vdA0KPiA+IGRlZmlu
ZSB0aGUgY29ycmVzcG9uZGluZyByYW5nZXMgcHJvcGVydHk7DQo+ID4NCj4gPiBUaGVyZSBhcmUg
c29tZSBzcGVjaWFsIElTQS9MUEMgZGV2aWNlcyB0aGF0IHdvcmsgb24gYSBzcGVjaWZpYyBJL08N
Cj4gcmFuZ2Ugd2hlcmUNCj4gPiBpdCBpcyBub3QgY29ycmVjdCB0byBzcGVjaWZ5IGEgcmFuZ2Vz
IHByb3BlcnR5IGluIERUUyBwYXJlbnQgbm9kZSBhcw0KPiBjcHUNCj4gPiBhZGRyZXNzZXMgdHJh
bnNsYXRlZCBmcm9tIERUUyBub2RlIGFyZSBvbmx5IGZvciBtZW1vcnkgc3BhY2Ugb24gc29tZQ0K
PiA+IGFyY2hpdGVjdHVyZXMsIHN1Y2ggYXMgQXJtNjQuIFdpdGhvdXQgdGhlIHBhcmVudCAncmFu
Z2VzJyBwcm9wZXJ0eSwNCj4gY3VycmVudA0KPiA+IG9mX3RyYW5zbGF0ZV9hZGRyZXNzKCkgcmV0
dXJuIGFuIGVycm9yLg0KPiA+IEhlcmUgd2UgYWRkIGEgZml4dXAgZnVuY3Rpb24sIG9mX2dldF9p
c2FfaW5kaXJlY3RfaW8oKS4gRHVyaW5nIHRoZSBPRg0KPiBhZGRyZXNzDQo+ID4gdHJhbnNsYXRp
b24sIHRoaXMgZml4dXAgd2lsbCBiZSBjYWxsZWQgdG8gY2hlY2sgdGhlICdyZWcnIGFkZHJlc3Mg
dG8NCj4gYmUNCj4gPiB0cmFuc2xhdGluZyBpcyBmb3IgdGhvc2Ugc2VwY2lhbCBJU0EvTFBDIGRl
dmljZXMgYW5kIGdldCB0aGUgSS9PDQo+IHJhbmdlDQo+ID4gZGlyZWN0bHkgZnJvbSB0aGUgJ3Jl
ZycgcHJvcGVydHkuDQo+ID4NCj4gPiAyKSBlbGltaW5hdGUgdGhlIEkvTyByYW5nZSBjb25mbGlj
dCByaXNrIHdpdGggUENJL1BDSUUgbGVhZ2VjeSBJL08NCj4gZGV2aWNlOw0KPiA+DQo+ID4gVGhl
IGN1cnJlbnQgX19vZl9hZGRyZXNzX3RvX3Jlc291cmNlKCkgYWx3YXlzIHRyYW5zbGF0ZXMgdGhl
IEkvTw0KPiByYW5nZSB0byBQSU8uDQo+ID4gQnV0IHRoaXMgcHJvY2Vzc2luZyBpcyBub3Qgc3Vp
dGFibGUgZm9yIG91ciBJU0EvTFBDIGRldmljZXMgd2hvc2UgSS9PDQo+IHJhbmdlIGlzDQo+ID4g
bm90IGNwdSBhZGRyZXNzKEFybmQgaGFkIHN0cmVzc2VkIHRoaXMgaW4gaGlzIGNvbW1lbnRzIG9u
IFYyLFYzDQo+IHBhdGNoLXNldCkuDQo+ID4gSGVyZSwgd2UgYnlwYXNzIHRoZSBtYXBwaW5nIGJl
dHdlZW4gY3B1IGFkZHJlc3MgYW5kIFBJTyBmb3IgdGhlDQo+IHNwZWNpYWwNCj4gPiBJU0EvTFBD
IGRldmljZXMuIEJ1dCB0byBkcml2ZSB0aGVzZSBJU0EvTFBDIGRldmljZXMsIGEgSS9PIHBvcnQN
Cj4gYWRkcmVzcyBiZWxvdw0KPiA+IFBDSUJJT1NfTUlOX0lPIGlzIG5lZWRlZCBieSBpbiovb3V0
KigpLiBXaGljaCBtZWFucyB0aGVyZSBpcyBjb25mbGljdA0KPiByaXNrDQo+ID4gYmV0d2VlbiBJ
L08gcmFuZ2Ugb2YgWzAsIFBDSUJJT1NfTUlOX0lPKSBhbmQgUENJL1BDSUUgbGVnYWN5IEkvTw0K
PiByYW5nZSBvZiBbMCwNCj4gPiBJT19TUEFDRV9MSU1JVCkuDQo+ID4gVG8gYXZvaWQgdGhlIEkv
TyBjb25mbGljdCwgdGhpcyBwYXRjaCByZXNlcnZlIHRoZSBJL08gcmFuZ2UgYmVsb3cNCj4gPiBQ
Q0lCSU9TX01JTl9JTy4NCj4gPg0KPiA+IFNpZ25lZC1vZmYtYnk6IHpoaWNoYW5nLnl1YW4gPHl1
YW56aGljaGFuZ0BoaXNpbGljb24uY29tPg0KPiA+IFNpZ25lZC1vZmYtYnk6IEdhYnJpZWxlIFBh
b2xvbmkgPGdhYnJpZWxlLnBhb2xvbmlAaHVhd2VpLmNvbT4NCj4gPiAtLS0NCj4gPiAgLi4uL2Fy
bS9oaXNpbGljb24vaGlzaWxpY29uLWxvdy1waW4tY291bnQudHh0ICAgICAgfCAzMSArKysrKysr
KysrKysNCj4gPiAgYXJjaC9hcm02NC9pbmNsdWRlL2FzbS9pby5oICAgICAgICAgICAgICAgICAg
ICAgICAgfCAgNiArKysNCj4gPiAgYXJjaC9hcm02NC9rZXJuZWwvZXh0aW8uYyAgICAgICAgICAg
ICAgICAgICAgICAgICAgfCAyNSArKysrKysrKysrDQo+ID4gIGRyaXZlcnMvb2YvYWRkcmVzcy5j
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNTYNCj4gKysrKysrKysrKysrKysrKysr
KysrLQ0KPiA+ICBkcml2ZXJzL3BjaS9wY2kuYyAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICB8ICA2ICstLQ0KPiA+ICBpbmNsdWRlL2xpbnV4L29mX2FkZHJlc3MuaCAgICAgICAgICAg
ICAgICAgICAgICAgICB8IDE3ICsrKysrKysNCj4gPiAgaW5jbHVkZS9saW51eC9wY2kuaCAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAgOCArKysrDQo+ID4gIDcgZmlsZXMgY2hhbmdl
ZCwgMTQ1IGluc2VydGlvbnMoKyksIDQgZGVsZXRpb25zKC0pDQo+ID4gIGNyZWF0ZSBtb2RlIDEw
MDY0NA0KPiBEb2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3MvYXJtL2hpc2lsaWNvbi9o
aXNpbGljb24tbG93LXBpbi0NCj4gY291bnQudHh0DQo+ID4NCj4gPiBkaWZmIC0tZ2l0DQo+IGEv
RG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdzL2FybS9oaXNpbGljb24vaGlzaWxpY29u
LWxvdy1waW4tDQo+IGNvdW50LnR4dCBiL0RvY3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5kaW5n
cy9hcm0vaGlzaWxpY29uL2hpc2lsaWNvbi0NCj4gbG93LXBpbi1jb3VudC50eHQNCj4gPiBuZXcg
ZmlsZSBtb2RlIDEwMDY0NA0KPiA+IGluZGV4IDAwMDAwMDAuLjEzYzhkZGQNCj4gPiAtLS0gL2Rl
di9udWxsDQo+ID4gKysrIGIvRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdzL2FybS9o
aXNpbGljb24vaGlzaWxpY29uLWxvdy0NCj4gcGluLWNvdW50LnR4dA0KPiA+IEBAIC0wLDAgKzEs
MzEgQEANCj4gPiArSGlzaWxpY29uIEhpcDA2IGxvdy1waW4tY291bnQgZGV2aWNlDQo+ID4gKyAg
VXN1YWxseSBMUEMgY29udHJvbGxlciBpcyBwYXJ0IG9mIFBDSSBob3N0IGJyaWRnZSwgc28gdGhl
IGxlZ2FjeQ0KPiBJU0EgcG9ydHMNCj4gPiArICBsb2NhdGUgb24gTFBDIGJ1cyBjYW4gYmUgYWNj
ZXNzZWQgZGlyZWNsdHkuIEJ1dCBzb21lIFNvQ3MgaGF2ZQ0KPiBpbmRlcGVuZGVudA0KPiA+ICsg
IExQQyBjb250cm9sbGVyLCBhbmQgYWNjZXNzIHRoZSBsZWdhY3kgcG9ydHMgYnkgdHJpZ2dlcmlu
ZyBMUEMgSS9PDQo+IGN5Y2xlcy4NCj4gPiArICBIaXNpbGljb24gSGlwMDYgaW1wbGVtZW50cyB0
aGlzIExQQyBkZXZpY2UuDQo+ID4gKw0KPiA+ICtSZXF1aXJlZCBwcm9wZXJ0aWVzOg0KPiA+ICst
IGNvbXBhdGlibGU6IHNob3VsZCBiZSAiaGlzaWxpY29uLGxvdy1waW4tY291bnQiDQo+ID4gKy0g
I2FkZHJlc3MtY2VsbHM6IG11c3QgYmUgMiB3aGljaCBzdGljayB0byB0aGUgSVNBL0VJU0EgYmlu
ZGluZyBkb2MuDQo+ID4gKy0gI3NpemUtY2VsbHM6IG11c3QgYmUgMSB3aGljaCBzdGljayB0byB0
aGUgSVNBL0VJU0EgYmluZGluZyBkb2MuDQo+ID4gKy0gcmVnOiBiYXNlIG1lbW9yeSByYW5nZSB3
aGVyZSB0aGUgcmVnaXN0ZXIgc2V0IG9mIHRoaXMgZGV2aWNlIGlzDQo+IG1hcHBlZC4NCj4gPiAr
DQo+ID4gK05vdGU6DQo+ID4gKyAgVGhlIG5vZGUgbmFtZSBiZWZvcmUgJ0AnIG11c3QgYmUgImlz
YSIgdG8gcmVwcmVzZW50IHRoZSBiaW5kaW5nDQo+IHN0aWNrIHRvIHRoZQ0KPiA+ICsgIElTQS9F
SVNBIGJpbmRpbmcgc3BlY2lmaWNhdGlvbi4NCj4gPiArDQo+ID4gK0V4YW1wbGU6DQo+ID4gKw0K
PiA+ICtpc2FAYTAxYjAwMDAgew0KPiA+ICsJY29tcGF0aWJsZSA9ICJoaXNpbGljb20sbG93LXBp
bi1jb3VudCI7DQo+ID4gKwkjYWRkcmVzcy1jZWxscyA9IDwyPjsNCj4gPiArCSNzaXplLWNlbGxz
ID0gPDE+Ow0KPiA+ICsJcmVnID0gPDB4MCAweGEwMWIwMDAwIDB4MCAweDEwMDA+Ow0KPiA+ICsN
Cj4gPiArCWlwbWkwOiBidEBlNCB7DQo+ID4gKwkJY29tcGF0aWJsZSA9ICJpcG1pLWJ0IjsNCj4g
PiArCQlkZXZpY2VfdHlwZSA9ICJpcG1pIjsNCj4gPiArCQlyZWcgPSA8MHgwMSAweGU0IDB4MDQ+
Ow0KPiA+ICsJCXN0YXR1cyA9ICJkaXNhYmxlZCI7DQo+ID4gKwl9Ow0KPiA+ICt9Ow0KPiANCj4g
DQo+IFRoaXMgZG9jdW1lbnRhdGlvbiBmaWxlIG5lZWRzIHRvIGJlIHBhcnQgb2YgdGhlIG5leHQg
cGF0Y2guIEl0IGhhcw0KPiBub3RoaW5nIHRvIGRvIHdpdGgNCj4gd2hhdCB5b3UgYXJlIHRyeWlu
ZyB0byBmaXggaGVyZS4NCg0KWWVzIHlvdSdyZSByaWdodC4uLndlJ2xsIG1vdmUgaXQgdG8gbmV4
dCBvbmUNCg0KPiANCj4gDQo+ID4gZGlmZiAtLWdpdCBhL2FyY2gvYXJtNjQvaW5jbHVkZS9hc20v
aW8uaA0KPiBiL2FyY2gvYXJtNjQvaW5jbHVkZS9hc20vaW8uaA0KPiA+IGluZGV4IDEzNjczNWQu
LmMyNmI3Y2MgMTAwNjQ0DQo+ID4gLS0tIGEvYXJjaC9hcm02NC9pbmNsdWRlL2FzbS9pby5oDQo+
ID4gKysrIGIvYXJjaC9hcm02NC9pbmNsdWRlL2FzbS9pby5oDQo+ID4gQEAgLTE3NSw2ICsxNzUs
MTIgQEAgc3RhdGljIGlubGluZSB1NjQgX19yYXdfcmVhZHEoY29uc3Qgdm9sYXRpbGUNCj4gdm9p
ZCBfX2lvbWVtICphZGRyKQ0KPiA+ICAjZGVmaW5lIG91dHNsIG91dHNsDQo+ID4NCj4gPiAgREVD
TEFSRV9FWFRJTyhsLCB1MzIpDQo+ID4gKw0KPiA+ICsjZGVmaW5lIGluZGlyZWN0X2lvX2VuYWJs
ZWQgaW5kaXJlY3RfaW9fZW5hYmxlZA0KPiA+ICtleHRlcm4gYm9vbCBpbmRpcmVjdF9pb19lbmFi
bGVkKHZvaWQpOw0KPiA+ICsNCj4gPiArI2RlZmluZSBhZGRyX2lzX2luZGlyZWN0X2lvIGFkZHJf
aXNfaW5kaXJlY3RfaW8NCj4gPiArZXh0ZXJuIGludCBhZGRyX2lzX2luZGlyZWN0X2lvKHU2NCB0
YWRkcik7DQo+ID4gICNlbmRpZg0KPiA+DQo+ID4NCj4gPiBkaWZmIC0tZ2l0IGEvYXJjaC9hcm02
NC9rZXJuZWwvZXh0aW8uYyBiL2FyY2gvYXJtNjQva2VybmVsL2V4dGlvLmMNCj4gPiBpbmRleCA2
NDdiM2ZhLi4zZDQ1ZmE4IDEwMDY0NA0KPiA+IC0tLSBhL2FyY2gvYXJtNjQva2VybmVsL2V4dGlv
LmMNCj4gPiArKysgYi9hcmNoL2FybTY0L2tlcm5lbC9leHRpby5jDQo+ID4gQEAgLTE5LDYgKzE5
LDMxIEBADQo+ID4NCj4gPiAgc3RydWN0IGV4dGlvX29wcyAqYXJtNjRfZXh0aW9fb3BzOw0KPiA+
DQo+ID4gKy8qKg0KPiA+ICsgKiBpbmRpcmVjdF9pb19lbmFibGVkIC0gY2hlY2sgd2hldGhlciBp
bmRpcmVjdElPIGlzIGVuYWJsZWQuDQo+ID4gKyAqCWFybTY0X2V4dGlvX29wcyB3aWxsIGJlIHNl
dCBvbmx5IHdoZW4gaW5kaXJlY3RJTyBtZWNoYW5pc20gaGFkDQo+IGJlZW4NCj4gPiArICoJaW5p
dGlhbGl6ZWQuDQo+ID4gKyAqDQo+ID4gKyAqIFJldHVybnMgdHJ1ZSB3aGVuIGluZGlyZWN0SU8g
aXMgZW5hYmxlZC4NCj4gPiArICovDQo+ID4gK2Jvb2wgaW5kaXJlY3RfaW9fZW5hYmxlZCh2b2lk
KQ0KPiA+ICt7DQo+ID4gKwlyZXR1cm4gYXJtNjRfZXh0aW9fb3BzID8gdHJ1ZSA6IGZhbHNlOw0K
PiA+ICt9DQo+ID4gKw0KPiA+ICsvKioNCj4gPiArICogYWRkcl9pc19pbmRpcmVjdF9pbyAtIGNo
ZWNrIHdoZXRoZXIgdGhlIGlucHV0IHRhZGRyIGlzIGZvcg0KPiBpbmRpcmVjdElPLg0KPiA+ICsg
KiBAdGFkZHI6IHRoZSBpbyBhZGRyZXNzIHRvIGJlIGNoZWNrZWQuDQo+ID4gKyAqDQo+ID4gKyAq
IFJldHVybnMgMSB3aGVuIHRhZGRyIGlzIGluIHRoZSByYW5nZTsgb3RoZXJ3aXNlIHJldHVybiAw
Lg0KPiA+ICsgKi8NCj4gPiAraW50IGFkZHJfaXNfaW5kaXJlY3RfaW8odTY0IHRhZGRyKQ0KPiA+
ICt7DQo+ID4gKwlpZiAoYXJtNjRfZXh0aW9fb3BzLT5zdGFydCA+IHRhZGRyIHx8IGFybTY0X2V4
dGlvX29wcy0+ZW5kIDwNCj4gdGFkZHIpDQo+IA0KPiBzdGFydCA+PSB0YWRkciA/DQoNCk5vcGUu
Li4gaWYgICh0YWRkciA8IGFybTY0X2V4dGlvX29wcy0+c3RhcnQgfHwgdGFkZHIgPiBhcm02NF9l
eHRpb19vcHMtPmVuZCkNCnRoZW4gdGFkZHIgaXMgb3V0c2lkZSB0aGUgcmFuZ2UgW3N0YXJ0OyBl
bmRdIGFuZCB3aWxsIHJldHVybiAwOyBvdGhlcndpc2UNCml0IHdpbGwgcmV0dXJuIDEuLi4NCg0K
PiANCj4gPiArCQlyZXR1cm4gMDsNCj4gPiArDQo+ID4gKwlyZXR1cm4gMTsNCj4gPiArfQ0KPiA+
DQo+ID4gIEJVSUxEX0VYVElPKGIsIHU4KQ0KPiA+DQo+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMv
b2YvYWRkcmVzcy5jIGIvZHJpdmVycy9vZi9hZGRyZXNzLmMNCj4gPiBpbmRleCAwMmIyOTAzLi5j
YzJhMDVkIDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvb2YvYWRkcmVzcy5jDQo+ID4gKysrIGIv
ZHJpdmVycy9vZi9hZGRyZXNzLmMNCj4gPiBAQCAtNDc5LDYgKzQ3OSw1MCBAQCBzdGF0aWMgaW50
IG9mX2VtcHR5X3Jhbmdlc19xdWlyayhzdHJ1Y3QNCj4gZGV2aWNlX25vZGUgKm5wKQ0KPiA+ICAJ
cmV0dXJuIGZhbHNlOw0KPiA+ICB9DQo+ID4NCj4gPiArDQo+ID4gKy8qDQo+ID4gKyAqIG9mX2lz
YV9pbmRpcmVjdF9pbyAtIGdldCB0aGUgSU8gYWRkcmVzcyBmcm9tIHNvbWUgaXNhIHJlZw0KPiBw
cm9wZXJ0eSB2YWx1ZS4NCj4gPiArICoJRm9yIHNvbWUgaXNhL2xwYyBkZXZpY2VzLCBubyByYW5n
ZXMgcHJvcGVydHkgaW4gYW5jZXN0b3Igbm9kZS4NCj4gPiArICoJVGhlIGRldmljZSBhZGRyZXNz
ZXMgYXJlIGRlc2NyaWJlZCBkaXJlY3RseSBpbiB0aGVpciByZWdzDQo+IHByb3BlcnR5Lg0KPiA+
ICsgKglUaGlzIGZpeHVwIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkIHRvIGdldCB0aGUgSU8gYWRk
cmVzcyBvZg0KPiBpc2EvbHBjDQo+ID4gKyAqCWRldmljZXMgd2hlbiB0aGUgbm9ybWFsIG9mX3Ry
YW5zbGF0aW9uIGZhaWxlZC4NCj4gPiArICoNCj4gPiArICogQHBhcmVudDoJcG9pbnRzIHRvIHRo
ZSBwYXJlbnQgZHRzIG5vZGU7DQo+ID4gKyAqIEBidXM6CQlwb2ludHMgdG8gdGhlIG9mX2J1cyB3
aGljaCBjYW4gYmUgdXNlZCB0byBwYXJzZQ0KPiBhZGRyZXNzOw0KPiA+ICsgKiBAYWRkcjoJdGhl
IGFkZHJlc3MgZnJvbSByZWcgcHJvcGVydHk7DQo+ID4gKyAqIEBuYToJCXRoZSBhZGRyZXNzIGNl
bGwgY291bnRlciBvZiBAYWRkcjsNCj4gPiArICogQHByZXN1bHQ6CXN0b3JlIHRoZSBhZGRyZXNz
IHBhcmVzZWQgZnJvbSBAYWRkcjsNCj4gPiArICoNCj4gPiArICogcmV0dXJuIDEgd2hlbiBzdWNj
ZXNzZnVsbHkgZ2V0IHRoZSBJL08gYWRkcmVzczsNCj4gPiArICogMCB3aWxsIHJldHVybiBmb3Ig
c29tZSBmYWlsdXJlcy4NCj4gDQo+IEJhaCwgeW91IGFyZSByZXR1cm5pbmcgYSBzaWduZWQgaW50
LCB3aHkgMCBmb3IgZmFpbHVyZT8gUmV0dXJuIGENCj4gbmVnYXRpdmUgdmFsdWUgd2l0aA0KPiBl
cnJvciBjb2Rlcy4gT3RoZXJ3aXNlIGNoYW5nZSB0aGUgcmV0dXJuIHZhbHVlIGludG8gYSBib29s
Lg0KDQpZZXMgd2UnbGwgbW92ZSB0byBib29sDQoNCj4gDQo+ID4gKyAqLw0KPiA+ICtzdGF0aWMg
aW50IG9mX2dldF9pc2FfaW5kaXJlY3RfaW8oc3RydWN0IGRldmljZV9ub2RlICpwYXJlbnQsDQo+
ID4gKwkJCQlzdHJ1Y3Qgb2ZfYnVzICpidXMsIF9fYmUzMiAqYWRkciwNCj4gPiArCQkJCWludCBu
YSwgdTY0ICpwcmVzdWx0KQ0KPiA+ICt7DQo+ID4gKwl1bnNpZ25lZCBpbnQgZmxhZ3M7DQo+ID4g
Kwl1bnNpZ25lZCBpbnQgcmxlbjsNCj4gPiArDQo+ID4gKwkvKiB3aGV0aGVyIHN1cHBvcnQgaW5k
aXJlY3RJTyAqLw0KPiA+ICsJaWYgKCFpbmRpcmVjdF9pb19lbmFibGVkKCkpDQo+ID4gKwkJcmV0
dXJuIDA7DQo+ID4gKw0KPiA+ICsJaWYgKCFvZl9idXNfaXNhX21hdGNoKHBhcmVudCkpDQo+ID4g
KwkJcmV0dXJuIDA7DQo+ID4gKw0KPiA+ICsJZmxhZ3MgPSBidXMtPmdldF9mbGFncyhhZGRyKTsN
Cj4gPiArCWlmICghKGZsYWdzICYgSU9SRVNPVVJDRV9JTykpDQo+ID4gKwkJcmV0dXJuIDA7DQo+
ID4gKw0KPiA+ICsJLyogdGhlcmUgaXMgcmFuZ2VzIHByb3BlcnR5LCBhcHBseSB0aGUgbm9ybWFs
IHRyYW5zbGF0aW9uDQo+IGRpcmVjdGx5LiAqLw0KPiANCj4gcy90aGVyZSBpcyByYW5nZXMvaWYg
d2UgaGF2ZSBhICdyYW5nZXMnLw0KDQpUaGFua3MgZm9yIHNwb3R0aW5nIHRoaXMNCg0KPiANCj4g
PiArCWlmIChvZl9nZXRfcHJvcGVydHkocGFyZW50LCAicmFuZ2VzIiwgJnJsZW4pKQ0KPiA+ICsJ
CXJldHVybiAwOw0KPiA+ICsNCj4gPiArCSpwcmVzdWx0ID0gb2ZfcmVhZF9udW1iZXIoYWRkciAr
IDEsIG5hIC0gMSk7DQo+ID4gKwkvKiB0aGlzIGZpeHVwIGlzIG9ubHkgdmFsaWQgZm9yIHNwZWNp
ZmljIEkvTyByYW5nZS4gKi8NCj4gPiArCXJldHVybiBhZGRyX2lzX2luZGlyZWN0X2lvKCpwcmVz
dWx0KTsNCj4gPiArfQ0KPiA+ICsNCj4gPiAgc3RhdGljIGludCBvZl90cmFuc2xhdGVfb25lKHN0
cnVjdCBkZXZpY2Vfbm9kZSAqcGFyZW50LCBzdHJ1Y3QNCj4gb2ZfYnVzICpidXMsDQo+ID4gIAkJ
CSAgICBzdHJ1Y3Qgb2ZfYnVzICpwYnVzLCBfX2JlMzIgKmFkZHIsDQo+ID4gIAkJCSAgICBpbnQg
bmEsIGludCBucywgaW50IHBuYSwgY29uc3QgY2hhciAqcnByb3ApDQo+ID4gQEAgLTU5NSw2ICs2
MzksMTUgQEAgc3RhdGljIHU2NCBfX29mX3RyYW5zbGF0ZV9hZGRyZXNzKHN0cnVjdA0KPiBkZXZp
Y2Vfbm9kZSAqZGV2LA0KPiA+ICAJCQlyZXN1bHQgPSBvZl9yZWFkX251bWJlcihhZGRyLCBuYSk7
DQo+ID4gIAkJCWJyZWFrOw0KPiA+ICAJCX0NCj4gPiArCQkvKg0KPiA+ICsJCSAqIEZvciBpbmRp
cmVjdElPIGRldmljZSB3aGljaCBoYXMgbm8gcmFuZ2VzIHByb3BlcnR5LCBnZXQNCj4gPiArCQkg
KiB0aGUgYWRkcmVzcyBmcm9tIHJlZyBkaXJlY3RseS4NCj4gPiArCQkgKi8NCj4gPiArCQlpZiAo
b2ZfZ2V0X2lzYV9pbmRpcmVjdF9pbyhkZXYsIGJ1cywgYWRkciwgbmEsICZyZXN1bHQpKSB7DQo+
ID4gKwkJCXByX2RlYnVnKCJpc2EgaW5kaXJlY3RJTyBtYXRjaGVkKCVzKS4uYWRkciA9DQo+IDB4
JWxseFxuIiwNCj4gPiArCQkJCW9mX25vZGVfZnVsbF9uYW1lKGRldiksIHJlc3VsdCk7DQo+ID4g
KwkJCWJyZWFrOw0KPiA+ICsJCX0NCj4gPg0KPiA+ICAJCS8qIEdldCBuZXcgcGFyZW50IGJ1cyBh
bmQgY291bnRzICovDQo+ID4gIAkJcGJ1cyA9IG9mX21hdGNoX2J1cyhwYXJlbnQpOw0KPiA+IEBA
IC02ODgsOCArNzQxLDkgQEAgc3RhdGljIGludCBfX29mX2FkZHJlc3NfdG9fcmVzb3VyY2Uoc3Ry
dWN0DQo+IGRldmljZV9ub2RlICpkZXYsDQo+ID4gIAlpZiAodGFkZHIgPT0gT0ZfQkFEX0FERFIp
DQo+ID4gIAkJcmV0dXJuIC1FSU5WQUw7DQo+ID4gIAltZW1zZXQociwgMCwgc2l6ZW9mKHN0cnVj
dCByZXNvdXJjZSkpOw0KPiA+IC0JaWYgKGZsYWdzICYgSU9SRVNPVVJDRV9JTykgew0KPiA+ICsJ
aWYgKGZsYWdzICYgSU9SRVNPVVJDRV9JTyAmJiB0YWRkciA+PSBQQ0lCSU9TX01JTl9JTykgew0K
PiA+ICAJCXVuc2lnbmVkIGxvbmcgcG9ydDsNCj4gPiArDQo+ID4gIAkJcG9ydCA9IHBjaV9hZGRy
ZXNzX3RvX3Bpbyh0YWRkcik7DQo+ID4gIAkJaWYgKHBvcnQgPT0gKHVuc2lnbmVkIGxvbmcpLTEp
DQo+ID4gIAkJCXJldHVybiAtRUlOVkFMOw0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3BjaS9w
Y2kuYyBiL2RyaXZlcnMvcGNpL3BjaS5jDQo+ID4gaW5kZXggYmEzNDkwNy4uMWEwODUxMSAxMDA2
NDQNCj4gPiAtLS0gYS9kcml2ZXJzL3BjaS9wY2kuYw0KPiA+ICsrKyBiL2RyaXZlcnMvcGNpL3Bj
aS5jDQo+ID4gQEAgLTMyNjMsNyArMzI2Myw3IEBAIGludCBfX3dlYWsgcGNpX3JlZ2lzdGVyX2lv
X3JhbmdlKHBoeXNfYWRkcl90DQo+IGFkZHIsIHJlc291cmNlX3NpemVfdCBzaXplKQ0KPiA+DQo+
ID4gICNpZmRlZiBQQ0lfSU9CQVNFDQo+ID4gIAlzdHJ1Y3QgaW9fcmFuZ2UgKnJhbmdlOw0KPiA+
IC0JcmVzb3VyY2Vfc2l6ZV90IGFsbG9jYXRlZF9zaXplID0gMDsNCj4gPiArCXJlc291cmNlX3Np
emVfdCBhbGxvY2F0ZWRfc2l6ZSA9IFBDSUJJT1NfTUlOX0lPOw0KPiA+DQo+ID4gIAkvKiBjaGVj
ayBpZiB0aGUgcmFuZ2UgaGFzbid0IGJlZW4gcHJldmlvdXNseSByZWNvcmRlZCAqLw0KPiA+ICAJ
c3Bpbl9sb2NrKCZpb19yYW5nZV9sb2NrKTsNCj4gPiBAQCAtMzMxMiw3ICszMzEyLDcgQEAgcGh5
c19hZGRyX3QgcGNpX3Bpb190b19hZGRyZXNzKHVuc2lnbmVkIGxvbmcNCj4gcGlvKQ0KPiA+DQo+
ID4gICNpZmRlZiBQQ0lfSU9CQVNFDQo+ID4gIAlzdHJ1Y3QgaW9fcmFuZ2UgKnJhbmdlOw0KPiA+
IC0JcmVzb3VyY2Vfc2l6ZV90IGFsbG9jYXRlZF9zaXplID0gMDsNCj4gPiArCXJlc291cmNlX3Np
emVfdCBhbGxvY2F0ZWRfc2l6ZSA9IFBDSUJJT1NfTUlOX0lPOw0KPiANCj4gSGF2ZSB5b3UgY2hl
Y2tlZCB0aGF0IHBjaV9waW9fdG9fYWRkcmVzcyBzdGlsbCByZXR1cm5zIHZhbGlkIHZhbHVlcw0K
PiBhZnRlciB0aGlzPyBJIGtub3cgdGhhdA0KPiB5b3UgYXJlIHRyeWluZyB0byB0YWtlIGludG8g
YWNjb3VudCBQQ0lCSU9TX01JTl9JTyBsaW1pdCB3aGVuDQo+IGFsbG9jYXRpbmcgcmVzZXJ2aW5n
IHRoZSBJTyByYW5nZXMsDQo+IGJ1dCB0aGUgdmFsdWVzIGFkZGVkIGluIHRoZSBpb19yYW5nZV9s
aXN0IGFyZSBzdGlsbCBzdGFydGluZyBmcm9tIHplcm8sDQo+IG5vIGZyb20gUENJQklPU19NSU5f
SU8sDQoNCkkgdGhpbmsgeW91J3JlIHdyb25nIGhlcmUgYXMgaW4gcGNpX2FkZHJlc3NfdG9fcGlv
IHdlIGhhdmU6DQorCXJlc291cmNlX3NpemVfdCBvZmZzZXQgPSBQQ0lCSU9TX01JTl9JTzsNCg0K
VGhpcyBzaG91bGQgYmUgZW5vdWdoIHRvIGd1YXJhbnRlZSB0aGF0IHRoZSBQSU9zIHN0YXJ0IGF0
DQpQQ0lCSU9TX01JTl9JTy4uLnJpZ2h0Pw0KDQoNCj4gc28gdGhlIGNhbGN1bGF0aW9uIG9mIHRo
ZSBhZGRyZXNzIGluIHRoaXMgZnVuY3Rpb24gY291bGQgcmV0dXJuDQo+IG5lZ2F0aXZlIHZhbHVl
cyBjYXN0ZWQgdG8gcGNpX2FkZHJfdC4NCj4gDQo+IE1heWJlIHlvdSB3YW50IHRvIGFkanVzdCB0
aGUgcmFuZ2UtPnN0YXJ0IHZhbHVlIGluDQo+IHBjaV9yZWdpc3Rlcl9pb19yYW5nZSgpIGFzIHdl
bGwgdG8gaGF2ZSBpdA0KPiBvZmZzZXQgYnkgUENJQklPU19NSU5fSU8gYXMgd2VsbC4NCj4gDQo+
IEJlc3QgcmVnYXJkcywNCj4gTGl2aXUNCj4gDQo+ID4NCj4gPiAgCWlmIChwaW8gPiBJT19TUEFD
RV9MSU1JVCkNCj4gPiAgCQlyZXR1cm4gYWRkcmVzczsNCj4gPiBAQCAtMzMzNSw3ICszMzM1LDcg
QEAgdW5zaWduZWQgbG9uZyBfX3dlYWsNCj4gcGNpX2FkZHJlc3NfdG9fcGlvKHBoeXNfYWRkcl90
IGFkZHJlc3MpDQo+ID4gIHsNCj4gPiAgI2lmZGVmIFBDSV9JT0JBU0UNCj4gPiAgCXN0cnVjdCBp
b19yYW5nZSAqcmVzOw0KPiA+IC0JcmVzb3VyY2Vfc2l6ZV90IG9mZnNldCA9IDA7DQo+ID4gKwly
ZXNvdXJjZV9zaXplX3Qgb2Zmc2V0ID0gUENJQklPU19NSU5fSU87DQo+ID4gIAl1bnNpZ25lZCBs
b25nIGFkZHIgPSAtMTsNCj4gPg0KPiA+ICAJc3Bpbl9sb2NrKCZpb19yYW5nZV9sb2NrKTsNCj4g
PiBkaWZmIC0tZ2l0IGEvaW5jbHVkZS9saW51eC9vZl9hZGRyZXNzLmggYi9pbmNsdWRlL2xpbnV4
L29mX2FkZHJlc3MuaA0KPiA+IGluZGV4IDM3ODY0NzMuLmRlZWM0NjkgMTAwNjQ0DQo+ID4gLS0t
IGEvaW5jbHVkZS9saW51eC9vZl9hZGRyZXNzLmgNCj4gPiArKysgYi9pbmNsdWRlL2xpbnV4L29m
X2FkZHJlc3MuaA0KPiA+IEBAIC0yNCw2ICsyNCwyMyBAQCBzdHJ1Y3Qgb2ZfcGNpX3JhbmdlIHsN
Cj4gPiAgI2RlZmluZSBmb3JfZWFjaF9vZl9wY2lfcmFuZ2UocGFyc2VyLCByYW5nZSkgXA0KPiA+
ICAJZm9yICg7IG9mX3BjaV9yYW5nZV9wYXJzZXJfb25lKHBhcnNlciwgcmFuZ2UpOykNCj4gPg0K
PiA+ICsNCj4gPiArI2lmbmRlZiBpbmRpcmVjdF9pb19lbmFibGVkDQo+ID4gKyNkZWZpbmUgaW5k
aXJlY3RfaW9fZW5hYmxlZCBpbmRpcmVjdF9pb19lbmFibGVkDQo+ID4gK3N0YXRpYyBpbmxpbmUg
Ym9vbCBpbmRpcmVjdF9pb19lbmFibGVkKHZvaWQpDQo+ID4gK3sNCj4gPiArCXJldHVybiBmYWxz
ZTsNCj4gPiArfQ0KPiA+ICsjZW5kaWYNCj4gPiArDQo+ID4gKyNpZm5kZWYgYWRkcl9pc19pbmRp
cmVjdF9pbw0KPiA+ICsjZGVmaW5lIGFkZHJfaXNfaW5kaXJlY3RfaW8gYWRkcl9pc19pbmRpcmVj
dF9pbw0KPiA+ICtzdGF0aWMgaW5saW5lIGludCBhZGRyX2lzX2luZGlyZWN0X2lvKHU2NCB0YWRk
cikNCj4gPiArew0KPiA+ICsJcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArI2VuZGlmDQo+ID4gKw0K
PiA+ICAvKiBUcmFuc2xhdGUgYSBETUEgYWRkcmVzcyBmcm9tIGRldmljZSBzcGFjZSB0byBDUFUg
c3BhY2UgKi8NCj4gPiAgZXh0ZXJuIHU2NCBvZl90cmFuc2xhdGVfZG1hX2FkZHJlc3Moc3RydWN0
IGRldmljZV9ub2RlICpkZXYsDQo+ID4gIAkJCQkgICAgY29uc3QgX19iZTMyICppbl9hZGRyKTsN
Cj4gPiBkaWZmIC0tZ2l0IGEvaW5jbHVkZS9saW51eC9wY2kuaCBiL2luY2x1ZGUvbGludXgvcGNp
LmgNCj4gPiBpbmRleCAwZTQ5ZjcwLi43ZjZiYmI2IDEwMDY0NA0KPiA+IC0tLSBhL2luY2x1ZGUv
bGludXgvcGNpLmgNCj4gPiArKysgYi9pbmNsdWRlL2xpbnV4L3BjaS5oDQo+ID4gQEAgLTIxMzAs
NCArMjEzMCwxMiBAQCBzdGF0aWMgaW5saW5lIGJvb2wgcGNpX2FyaV9lbmFibGVkKHN0cnVjdA0K
PiBwY2lfYnVzICpidXMpDQo+ID4gIC8qIHByb3ZpZGUgdGhlIGxlZ2FjeSBwY2lfZG1hXyogQVBJ
ICovDQo+ID4gICNpbmNsdWRlIDxsaW51eC9wY2ktZG1hLWNvbXBhdC5oPg0KPiA+DQo+ID4gKy8q
DQo+ID4gKyAqIGRlZmluZSB0aGlzIG1hY3JvIGhlcmUgdG8gcmVmcmFpbiBmcm9tIGNvbXBpbGF0
aW9uIGVycm9yIGZvciBzb21lDQo+ID4gKyAqIHBsYXRmb3Jtcy4gUGxlYXNlIGtlZXAgdGhpcyBt
YWNybyBhdCB0aGUgZW5kIG9mIHRoaXMgaGVhZGVyIGZpbGUuDQo+ID4gKyAqLw0KPiA+ICsjaWZu
ZGVmIFBDSUJJT1NfTUlOX0lPDQo+ID4gKyNkZWZpbmUgUENJQklPU19NSU5fSU8JCTANCj4gPiAr
I2VuZGlmDQo+ID4gKw0KPiA+ICAjZW5kaWYgLyogTElOVVhfUENJX0ggKi8NCj4gPiAtLQ0KPiA+
IDEuOS4xDQo+ID4NCj4gPiAtLQ0KPiA+IFRvIHVuc3Vic2NyaWJlIGZyb20gdGhpcyBsaXN0OiBz
ZW5kIHRoZSBsaW5lICJ1bnN1YnNjcmliZSBsaW51eC1wY2kiDQo+IGluDQo+ID4gdGhlIGJvZHkg
b2YgYSBtZXNzYWdlIHRvIG1ham9yZG9tb0B2Z2VyLmtlcm5lbC5vcmcNCj4gPiBNb3JlIG1ham9y
ZG9tbyBpbmZvIGF0ICBodHRwOi8vdmdlci5rZXJuZWwub3JnL21ham9yZG9tby1pbmZvLmh0bWwN
Cj4gDQo+IC0tDQo+ID09PT09PT09PT09PT09PT09PT09DQo+IHwgSSB3b3VsZCBsaWtlIHRvIHwN
Cj4gfCBmaXggdGhlIHdvcmxkLCAgfA0KPiB8IGJ1dCB0aGV5J3JlIG5vdCB8DQo+IHwgZ2l2aW5n
IG1lIHRoZSAgIHwNCj4gIFwgc291cmNlIGNvZGUhICAvDQo+ICAgLS0tLS0tLS0tLS0tLS0tDQo+
ICAgICDCr1xfKOODhClfL8KvDQo=

^ permalink raw reply

* [PATCH igt v3 00/11] corresponding changes for i915-perf interface
From: Robert Bragg @ 2016-11-09 16:15 UTC (permalink / raw)
  To: intel-gfx

The i915-perf series affects the command parser and itself includes new uapi
which these i-g-t changes try to cover.

As well as splitting up the gem_exec_parse changes this version maintains
support for testing version 7 of the command parser.

- Robert

Robert Bragg (6):
  igt/perf: add i915 perf stream tests for Haswell
  igt/gem_exec_parse: remove oacontrol checks
  igt/gem_exec_parse: some minor cleanups
  igt/gem_exec_parse: move hsw_load_register_reg down
  igt/gem_exec_parse: update hsw_load_register_reg
  igt/gem_exec_parse: update for version 8 changes

 tests/Makefile.sources |    1 +
 tests/gem_exec_parse.c |  519 +++++------
 tests/perf.c           | 2220 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 2429 insertions(+), 311 deletions(-)
 create mode 100644 tests/perf.c

-- 
2.10.1

*** BLURB HERE ***

Robert Bragg (11):
  igt/perf: add i915 perf stream tests for Haswell
  igt/gem_exec_parse: some minor cleanups
  igt/gem_exec_parse: move hsw_load_register_reg down
  igt/gem_exec_parse: update hsw_load_register_reg
  igt/gem_exec_parse: req. v < 9 for oacontrol tracking test
  igt/gem_exec_parse: make basic-rejected version agnostic
  igt/gem_exec_parse: update bitmasks test for v >=8
  igt/gem_exec_parse: update cmd-crossing-page for >= v8
  igt/gem_exec_parse: update hsw_load_register_reg for v >= 8
  igt/gem_exec_parse: update registers test for v >= 8
  igt/gem_exec_parse: check oacontrol lri bad for >= v9

 tests/Makefile.sources |    1 +
 tests/gem_exec_parse.c |  555 ++++++------
 tests/perf.c           | 2220 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 2501 insertions(+), 275 deletions(-)
 create mode 100644 tests/perf.c

-- 
2.10.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply

* [tip:x86/urgent] x86/cpu/AMD: Fix cpu_llc_id for AMD Fam17h systems
From: tip-bot for Yazen Ghannam @ 2016-11-09 16:13 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, torvalds, bp, tglx, peterz, linux-kernel, aravindksg.lkml,
	Yazen.Ghannam, mingo
In-Reply-To: <20161108083506.rvqb5h4chrcptj7d@pd.tnic>

Commit-ID:  b0b6e86846093c5f8820386bc01515f857dd8faa
Gitweb:     http://git.kernel.org/tip/b0b6e86846093c5f8820386bc01515f857dd8faa
Author:     Yazen Ghannam <Yazen.Ghannam@amd.com>
AuthorDate: Tue, 8 Nov 2016 09:35:06 +0100
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 9 Nov 2016 17:06:08 +0100

x86/cpu/AMD: Fix cpu_llc_id for AMD Fam17h systems

cpu_llc_id (Last Level Cache ID) derivation on AMD Fam17h has an
underflow bug when extracting the socket_id value. It starts from 0
so subtracting 1 from it will result in an invalid value. This breaks
scheduling topology later on since the cpu_llc_id will be incorrect.

For example, the the cpu_llc_id of the *other* CPU in the loops in
set_cpu_sibling_map() underflows and we're generating the funniest
thread_siblings masks and then when I run 8 threads of nbench, they get
spread around the LLC domains in a very strange pattern which doesn't
give you the normal scheduling spread one would expect for performance.

Other things like EDAC use cpu_llc_id so they will be b0rked too.

So, the APIC ID is preset in APICx020 for bits 3 and above: they contain
the core complex, node and socket IDs.

The LLC is at the core complex level so we can find a unique cpu_llc_id
by right shifting the APICID by 3 because then the least significant bit
will be the Core Complex ID.

Tested-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Yazen Ghannam <Yazen.Ghannam@amd.com>
[ Cleaned up and extended the commit message. ]
Signed-off-by: Borislav Petkov <bp@suse.de>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Cc: <stable@vger.kernel.org> # v4.4..
Cc: Aravind Gopalakrishnan <aravindksg.lkml@gmail.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Fixes: 3849e91f571d ("x86/AMD: Fix last level cache topology for AMD Fam17h systems")
Link: http://lkml.kernel.org/r/20161108083506.rvqb5h4chrcptj7d@pd.tnic
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/kernel/cpu/amd.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index b81fe2d..1e81a37 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -347,7 +347,6 @@ static void amd_detect_cmp(struct cpuinfo_x86 *c)
 #ifdef CONFIG_SMP
 	unsigned bits;
 	int cpu = smp_processor_id();
-	unsigned int socket_id, core_complex_id;
 
 	bits = c->x86_coreid_bits;
 	/* Low order bits define the core id (index of core in socket) */
@@ -365,10 +364,7 @@ static void amd_detect_cmp(struct cpuinfo_x86 *c)
 	 if (c->x86 != 0x17 || !cpuid_edx(0x80000006))
 		return;
 
-	socket_id	= (c->apicid >> bits) - 1;
-	core_complex_id	= (c->apicid & ((1 << bits) - 1)) >> 3;
-
-	per_cpu(cpu_llc_id, cpu) = (socket_id << 3) | core_complex_id;
+	per_cpu(cpu_llc_id, cpu) = c->apicid >> 3;
 #endif
 }
 

^ permalink raw reply related

* [PATCH v2 15/28] i.MX: Add VF610 clock tree initialization code
From: Andrey Smirnov @ 2016-11-09 16:14 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Based on analogous code from Linux kernel

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/clk/imx/Makefile    |   3 +-
 drivers/clk/imx/clk-vf610.c | 443 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 444 insertions(+), 2 deletions(-)
 create mode 100644 drivers/clk/imx/clk-vf610.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 06af530..ffaff1c 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -18,5 +18,4 @@ obj-$(CONFIG_ARCH_IMX51)  += clk-imx5.o
 obj-$(CONFIG_ARCH_IMX53)  += clk-imx5.o
 obj-$(CONFIG_ARCH_IMX6)   += clk-imx6.o
 obj-$(CONFIG_ARCH_IMX6SX) += clk-imx6sx.o
-
-
+obj-$(CONFIG_ARCH_VF610) += clk-vf610.o
diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c
new file mode 100644
index 0000000..04cb02f
--- /dev/null
+++ b/drivers/clk/imx/clk-vf610.c
@@ -0,0 +1,443 @@
+/*
+ * Copyright 2012-2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <io.h>
+#include <of.h>
+#include <of_address.h>
+#include <linux/clkdev.h>
+#include <linux/clk.h>
+#include <dt-bindings/clock/vf610-clock.h>
+
+#include "clk.h"
+
+#define CCM_CCR			(ccm_base + 0x00)
+#define CCM_CSR			(ccm_base + 0x04)
+#define CCM_CCSR		(ccm_base + 0x08)
+#define CCSR_PLL1_PFDn_EN(n)	BIT((n) + 7)
+#define CCSR_PLL2_PFDn_EN(n)	BIT((n) + 11)
+#define CCSR_PLL3_PFDn_EN(n)	BIT((n) + 27)
+#define CCM_CACRR		(ccm_base + 0x0c)
+#define CCM_CSCMR1		(ccm_base + 0x10)
+#define CCM_CSCDR1		(ccm_base + 0x14)
+#define CCM_CSCDR2		(ccm_base + 0x18)
+#define CCM_CSCDR3		(ccm_base + 0x1c)
+#define CCM_CSCMR2		(ccm_base + 0x20)
+#define CCM_CSCDR4		(ccm_base + 0x24)
+#define CCM_CLPCR		(ccm_base + 0x2c)
+#define CCM_CISR		(ccm_base + 0x30)
+#define CCM_CIMR		(ccm_base + 0x34)
+#define CCM_CGPR		(ccm_base + 0x3c)
+#define CCM_CCGR0		(ccm_base + 0x40)
+#define CCM_CCGR1		(ccm_base + 0x44)
+#define CCM_CCGR2		(ccm_base + 0x48)
+#define CCM_CCGR3		(ccm_base + 0x4c)
+#define CCM_CCGR4		(ccm_base + 0x50)
+#define CCM_CCGR5		(ccm_base + 0x54)
+#define CCM_CCGR6		(ccm_base + 0x58)
+#define CCM_CCGR7		(ccm_base + 0x5c)
+#define CCM_CCGR8		(ccm_base + 0x60)
+#define CCM_CCGR9		(ccm_base + 0x64)
+#define CCM_CCGR10		(ccm_base + 0x68)
+#define CCM_CCGR11		(ccm_base + 0x6c)
+#define CCM_CCGRx(x)		(CCM_CCGR0 + (x) * 4)
+#define CCM_CMEOR0		(ccm_base + 0x70)
+#define CCM_CMEOR1		(ccm_base + 0x74)
+#define CCM_CMEOR2		(ccm_base + 0x78)
+#define CCM_CMEOR3		(ccm_base + 0x7c)
+#define CCM_CMEOR4		(ccm_base + 0x80)
+#define CCM_CMEOR5		(ccm_base + 0x84)
+#define CCM_CPPDSR		(ccm_base + 0x88)
+#define CCM_CCOWR		(ccm_base + 0x8c)
+#define CCM_CCPGR0		(ccm_base + 0x90)
+#define CCM_CCPGR1		(ccm_base + 0x94)
+#define CCM_CCPGR2		(ccm_base + 0x98)
+#define CCM_CCPGR3		(ccm_base + 0x9c)
+
+#define CCM_CCGRx_CGn(n)	((n) * 2)
+
+#define PFD_PLL1_BASE		(anatop_base + 0x2b0)
+#define PFD_PLL2_BASE		(anatop_base + 0x100)
+#define PFD_PLL3_BASE		(anatop_base + 0xf0)
+#define PLL1_CTRL		(anatop_base + 0x270)
+#define PLL2_CTRL		(anatop_base + 0x30)
+#define PLL3_CTRL		(anatop_base + 0x10)
+#define PLL4_CTRL		(anatop_base + 0x70)
+#define PLL5_CTRL		(anatop_base + 0xe0)
+#define PLL6_CTRL		(anatop_base + 0xa0)
+#define PLL7_CTRL		(anatop_base + 0x20)
+#define ANA_MISC1		(anatop_base + 0x160)
+
+static void __iomem *anatop_base;
+static void __iomem *ccm_base;
+
+/* sources for multiplexer clocks, this is used multiple times */
+static const char *fast_sels[]	= { "firc", "fxosc", };
+static const char *slow_sels[]	= { "sirc_32k", "sxosc", };
+static const char *pll1_sels[]	= { "pll1_sys", "pll1_pfd1", "pll1_pfd2", "pll1_pfd3", "pll1_pfd4", };
+static const char *pll2_sels[]	= { "pll2_bus", "pll2_pfd1", "pll2_pfd2", "pll2_pfd3", "pll2_pfd4", };
+static const char *pll_bypass_src_sels[] = { "fast_clk_sel", "lvds1_in", };
+static const char *pll1_bypass_sels[] = { "pll1", "pll1_bypass_src", };
+static const char *pll2_bypass_sels[] = { "pll2", "pll2_bypass_src", };
+static const char *pll3_bypass_sels[] = { "pll3", "pll3_bypass_src", };
+static const char *pll4_bypass_sels[] = { "pll4", "pll4_bypass_src", };
+static const char *pll5_bypass_sels[] = { "pll5", "pll5_bypass_src", };
+static const char *pll6_bypass_sels[] = { "pll6", "pll6_bypass_src", };
+static const char *pll7_bypass_sels[] = { "pll7", "pll7_bypass_src", };
+static const char *sys_sels[]	= { "fast_clk_sel", "slow_clk_sel", "pll2_pfd_sel", "pll2_bus", "pll1_pfd_sel", "pll3_usb_otg", };
+static const char *ddr_sels[]	= { "pll2_pfd2", "sys_sel", };
+static const char *rmii_sels[]	= { "enet_ext", "audio_ext", "enet_50m", "enet_25m", };
+static const char *enet_ts_sels[]	= { "enet_ext", "fxosc", "audio_ext", "usb", "enet_ts", "enet_25m", "enet_50m", };
+static const char *esai_sels[]	= { "audio_ext", "mlb", "spdif_rx", "pll4_audio_div", };
+static const char *sai_sels[]	= { "audio_ext", "mlb", "spdif_rx", "pll4_audio_div", };
+static const char *nfc_sels[]	= { "platform_bus", "pll1_pfd1", "pll3_pfd1", "pll3_pfd3", };
+static const char *qspi_sels[]	= { "pll3_usb_otg", "pll3_pfd4", "pll2_pfd4", "pll1_pfd4", };
+static const char *esdhc_sels[]	= { "pll3_usb_otg", "pll3_pfd3", "pll1_pfd3", "platform_bus", };
+static const char *dcu_sels[]	= { "pll1_pfd2", "pll3_usb_otg", };
+static const char *gpu_sels[]	= { "pll2_pfd2", "pll3_pfd2", };
+static const char *vadc_sels[]	= { "pll6_video_div", "pll3_usb_otg_div", "pll3_usb_otg", };
+/* FTM counter clock source, not module clock */
+static const char *ftm_ext_sels[]	= {"sirc_128k", "sxosc", "fxosc_half", "audio_ext", };
+static const char *ftm_fix_sels[]	= { "sxosc", "ipg_bus", };
+
+
+static struct clk_div_table pll4_audio_div_table[] = {
+	{ .val = 0, .div = 1 },
+	{ .val = 1, .div = 2 },
+	{ .val = 2, .div = 6 },
+	{ .val = 3, .div = 8 },
+	{ .val = 4, .div = 10 },
+	{ .val = 5, .div = 12 },
+	{ .val = 6, .div = 14 },
+	{ .val = 7, .div = 16 },
+	{ }
+};
+
+static struct clk *clk[VF610_CLK_END];
+static struct clk_onecell_data clk_data;
+
+static unsigned int const clks_init_on[] __initconst = {
+	VF610_CLK_SYS_BUS,
+	VF610_CLK_DDR_SEL,
+	VF610_CLK_DAP,
+	VF610_CLK_DDRMC,
+	VF610_CLK_WKPU,
+};
+
+static void __init vf610_clocks_init(struct device_node *ccm_node)
+{
+	u32 ccsr;
+	struct device_node *np;
+	int i;
+
+	clk[VF610_CLK_DUMMY] = clk_fixed("dummy", 0);
+	clk[VF610_CLK_SIRC_128K] = clk_fixed("sirc_128k", 128000);
+	clk[VF610_CLK_SIRC_32K] = clk_fixed("sirc_32k", 32000);
+	clk[VF610_CLK_FIRC] = clk_fixed("firc", 24000000);
+
+	clk[VF610_CLK_SXOSC] = of_clk_get_by_name(ccm_node, "sxosc");
+	clk[VF610_CLK_FXOSC] = of_clk_get_by_name(ccm_node, "fxosc");
+	clk[VF610_CLK_AUDIO_EXT] = of_clk_get_by_name(ccm_node, "audio_ext");
+	clk[VF610_CLK_ENET_EXT] = of_clk_get_by_name(ccm_node, "enet_ext");
+
+	/* Clock source from external clock via LVDs PAD */
+	clk[VF610_CLK_ANACLK1] = of_clk_get_by_name(ccm_node, "anaclk1");
+
+	clk[VF610_CLK_FXOSC_HALF] = imx_clk_fixed_factor("fxosc_half", "fxosc", 1, 2);
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,vf610-anatop");
+	anatop_base = of_iomap(np, 0);
+	BUG_ON(!anatop_base);
+
+	np = ccm_node;
+	ccm_base = of_iomap(np, 0);
+	BUG_ON(!ccm_base);
+
+	ccsr = readl(CCM_CCSR);
+	ccsr |= CCSR_PLL3_PFDn_EN(1) |
+		CCSR_PLL3_PFDn_EN(2) |
+		CCSR_PLL3_PFDn_EN(3) |
+		CCSR_PLL3_PFDn_EN(4) |
+		CCSR_PLL2_PFDn_EN(1) |
+		CCSR_PLL2_PFDn_EN(2) |
+		CCSR_PLL2_PFDn_EN(3) |
+		CCSR_PLL2_PFDn_EN(4) |
+		CCSR_PLL1_PFDn_EN(1) |
+		CCSR_PLL1_PFDn_EN(2) |
+		CCSR_PLL1_PFDn_EN(3) |
+		CCSR_PLL1_PFDn_EN(4);
+	writel(ccsr, CCM_CCSR);
+
+	clk[VF610_CLK_SLOW_CLK_SEL] = imx_clk_mux("slow_clk_sel", CCM_CCSR, 4, 1, slow_sels, ARRAY_SIZE(slow_sels));
+	clk[VF610_CLK_FASK_CLK_SEL] = imx_clk_mux("fast_clk_sel", CCM_CCSR, 5, 1, fast_sels, ARRAY_SIZE(fast_sels));
+
+	clk[VF610_CLK_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", PLL1_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+	clk[VF610_CLK_PLL2_BYPASS_SRC] = imx_clk_mux("pll2_bypass_src", PLL2_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+	clk[VF610_CLK_PLL3_BYPASS_SRC] = imx_clk_mux("pll3_bypass_src", PLL3_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+	clk[VF610_CLK_PLL4_BYPASS_SRC] = imx_clk_mux("pll4_bypass_src", PLL4_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+	clk[VF610_CLK_PLL5_BYPASS_SRC] = imx_clk_mux("pll5_bypass_src", PLL5_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+	clk[VF610_CLK_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", PLL6_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+	clk[VF610_CLK_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", PLL7_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+
+	clk[VF610_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll1", "pll1_bypass_src", PLL1_CTRL, 0x1);
+	clk[VF610_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", PLL2_CTRL, 0x1);
+	clk[VF610_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB_VF610,     "pll3", "pll3_bypass_src", PLL3_CTRL, 0x2);
+	clk[VF610_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll4", "pll4_bypass_src", PLL4_CTRL, 0x7f);
+	clk[VF610_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_ENET,    "pll5", "pll5_bypass_src", PLL5_CTRL, 0x3);
+	clk[VF610_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll6", "pll6_bypass_src", PLL6_CTRL, 0x7f);
+	clk[VF610_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB_VF610,     "pll7", "pll7_bypass_src", PLL7_CTRL, 0x2);
+
+	clk[VF610_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", PLL1_CTRL, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
+	clk[VF610_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", PLL2_CTRL, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
+	clk[VF610_PLL3_BYPASS] = imx_clk_mux_flags("pll3_bypass", PLL3_CTRL, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT);
+	clk[VF610_PLL4_BYPASS] = imx_clk_mux_flags("pll4_bypass", PLL4_CTRL, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels), CLK_SET_RATE_PARENT);
+	clk[VF610_PLL5_BYPASS] = imx_clk_mux_flags("pll5_bypass", PLL5_CTRL, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT);
+	clk[VF610_PLL6_BYPASS] = imx_clk_mux_flags("pll6_bypass", PLL6_CTRL, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT);
+	clk[VF610_PLL7_BYPASS] = imx_clk_mux_flags("pll7_bypass", PLL7_CTRL, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT);
+
+	/* Do not bypass PLLs initially */
+	clk_set_parent(clk[VF610_PLL1_BYPASS], clk[VF610_CLK_PLL1]);
+	clk_set_parent(clk[VF610_PLL2_BYPASS], clk[VF610_CLK_PLL2]);
+	clk_set_parent(clk[VF610_PLL3_BYPASS], clk[VF610_CLK_PLL3]);
+	clk_set_parent(clk[VF610_PLL4_BYPASS], clk[VF610_CLK_PLL4]);
+	clk_set_parent(clk[VF610_PLL5_BYPASS], clk[VF610_CLK_PLL5]);
+	clk_set_parent(clk[VF610_PLL6_BYPASS], clk[VF610_CLK_PLL6]);
+	clk_set_parent(clk[VF610_PLL7_BYPASS], clk[VF610_CLK_PLL7]);
+
+	clk[VF610_CLK_PLL1_SYS]      = imx_clk_gate("pll1_sys",      "pll1_bypass", PLL1_CTRL, 13);
+	clk[VF610_CLK_PLL2_BUS]      = imx_clk_gate("pll2_bus",      "pll2_bypass", PLL2_CTRL, 13);
+	clk[VF610_CLK_PLL3_USB_OTG]  = imx_clk_gate("pll3_usb_otg",  "pll3_bypass", PLL3_CTRL, 13);
+	clk[VF610_CLK_PLL4_AUDIO]    = imx_clk_gate("pll4_audio",    "pll4_bypass", PLL4_CTRL, 13);
+	clk[VF610_CLK_PLL5_ENET]     = imx_clk_gate("pll5_enet",     "pll5_bypass", PLL5_CTRL, 13);
+	clk[VF610_CLK_PLL6_VIDEO]    = imx_clk_gate("pll6_video",    "pll6_bypass", PLL6_CTRL, 13);
+	clk[VF610_CLK_PLL7_USB_HOST] = imx_clk_gate("pll7_usb_host", "pll7_bypass", PLL7_CTRL, 13);
+
+	clk[VF610_CLK_LVDS1_IN]  = imx_clk_gate_exclusive("lvds1_in", "anaclk1", ANA_MISC1, 12, BIT(10));
+
+	clk[VF610_CLK_PLL1_PFD1] = imx_clk_pfd("pll1_pfd1", "pll1_sys", PFD_PLL1_BASE, 0);
+	clk[VF610_CLK_PLL1_PFD2] = imx_clk_pfd("pll1_pfd2", "pll1_sys", PFD_PLL1_BASE, 1);
+	clk[VF610_CLK_PLL1_PFD3] = imx_clk_pfd("pll1_pfd3", "pll1_sys", PFD_PLL1_BASE, 2);
+	clk[VF610_CLK_PLL1_PFD4] = imx_clk_pfd("pll1_pfd4", "pll1_sys", PFD_PLL1_BASE, 3);
+
+	clk[VF610_CLK_PLL2_PFD1] = imx_clk_pfd("pll2_pfd1", "pll2_bus", PFD_PLL2_BASE, 0);
+	clk[VF610_CLK_PLL2_PFD2] = imx_clk_pfd("pll2_pfd2", "pll2_bus", PFD_PLL2_BASE, 1);
+	clk[VF610_CLK_PLL2_PFD3] = imx_clk_pfd("pll2_pfd3", "pll2_bus", PFD_PLL2_BASE, 2);
+	clk[VF610_CLK_PLL2_PFD4] = imx_clk_pfd("pll2_pfd4", "pll2_bus", PFD_PLL2_BASE, 3);
+
+	clk[VF610_CLK_PLL3_PFD1] = imx_clk_pfd("pll3_pfd1", "pll3_usb_otg", PFD_PLL3_BASE, 0);
+	clk[VF610_CLK_PLL3_PFD2] = imx_clk_pfd("pll3_pfd2", "pll3_usb_otg", PFD_PLL3_BASE, 1);
+	clk[VF610_CLK_PLL3_PFD3] = imx_clk_pfd("pll3_pfd3", "pll3_usb_otg", PFD_PLL3_BASE, 2);
+	clk[VF610_CLK_PLL3_PFD4] = imx_clk_pfd("pll3_pfd4", "pll3_usb_otg", PFD_PLL3_BASE, 3);
+
+	clk[VF610_CLK_PLL1_PFD_SEL] = imx_clk_mux("pll1_pfd_sel", CCM_CCSR, 16, 3, pll1_sels, 5);
+	clk[VF610_CLK_PLL2_PFD_SEL] = imx_clk_mux("pll2_pfd_sel", CCM_CCSR, 19, 3, pll2_sels, 5);
+	clk[VF610_CLK_SYS_SEL] = imx_clk_mux("sys_sel", CCM_CCSR, 0, 3, sys_sels, ARRAY_SIZE(sys_sels));
+	clk[VF610_CLK_DDR_SEL] = imx_clk_mux("ddr_sel", CCM_CCSR, 6, 1, ddr_sels, ARRAY_SIZE(ddr_sels));
+	clk[VF610_CLK_SYS_BUS] = imx_clk_divider("sys_bus", "sys_sel", CCM_CACRR, 0, 3);
+	clk[VF610_CLK_PLATFORM_BUS] = imx_clk_divider("platform_bus", "sys_bus", CCM_CACRR, 3, 3);
+	clk[VF610_CLK_IPG_BUS] = imx_clk_divider("ipg_bus", "platform_bus", CCM_CACRR, 11, 2);
+
+	clk[VF610_CLK_PLL3_MAIN_DIV] = imx_clk_divider("pll3_usb_otg_div", "pll3_usb_otg", CCM_CACRR, 20, 1);
+	clk[VF610_CLK_PLL4_MAIN_DIV] = clk_divider_table("pll4_audio_div", "pll4_audio", CCM_CACRR, 6, 3, pll4_audio_div_table, 0);
+	clk[VF610_CLK_PLL6_MAIN_DIV] = imx_clk_divider("pll6_video_div", "pll6_video", CCM_CACRR, 21, 1);
+
+	clk[VF610_CLK_DDRMC] = imx_clk_gate2_cgr("ddrmc", "ddr_sel", CCM_CCGR6, CCM_CCGRx_CGn(14), 0x2);
+	clk[VF610_CLK_WKPU] = imx_clk_gate2_cgr("wkpu", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(10), 0x2);
+
+	clk[VF610_CLK_USBPHY0] = imx_clk_gate("usbphy0", "pll3_usb_otg", PLL3_CTRL, 6);
+	clk[VF610_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll7_usb_host", PLL7_CTRL, 6);
+
+	clk[VF610_CLK_USBC0] = imx_clk_gate2("usbc0", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(4));
+	clk[VF610_CLK_USBC1] = imx_clk_gate2("usbc1", "ipg_bus", CCM_CCGR7, CCM_CCGRx_CGn(4));
+
+	clk[VF610_CLK_QSPI0_SEL] = imx_clk_mux("qspi0_sel", CCM_CSCMR1, 22, 2, qspi_sels, 4);
+	clk[VF610_CLK_QSPI0_EN] = imx_clk_gate("qspi0_en", "qspi0_sel", CCM_CSCDR3, 4);
+	clk[VF610_CLK_QSPI0_X4_DIV] = imx_clk_divider("qspi0_x4", "qspi0_en", CCM_CSCDR3, 0, 2);
+	clk[VF610_CLK_QSPI0_X2_DIV] = imx_clk_divider("qspi0_x2", "qspi0_x4", CCM_CSCDR3, 2, 1);
+	clk[VF610_CLK_QSPI0_X1_DIV] = imx_clk_divider("qspi0_x1", "qspi0_x2", CCM_CSCDR3, 3, 1);
+	clk[VF610_CLK_QSPI0] = imx_clk_gate2("qspi0", "qspi0_x1", CCM_CCGR2, CCM_CCGRx_CGn(4));
+
+	clk[VF610_CLK_QSPI1_SEL] = imx_clk_mux("qspi1_sel", CCM_CSCMR1, 24, 2, qspi_sels, 4);
+	clk[VF610_CLK_QSPI1_EN] = imx_clk_gate("qspi1_en", "qspi1_sel", CCM_CSCDR3, 12);
+	clk[VF610_CLK_QSPI1_X4_DIV] = imx_clk_divider("qspi1_x4", "qspi1_en", CCM_CSCDR3, 8, 2);
+	clk[VF610_CLK_QSPI1_X2_DIV] = imx_clk_divider("qspi1_x2", "qspi1_x4", CCM_CSCDR3, 10, 1);
+	clk[VF610_CLK_QSPI1_X1_DIV] = imx_clk_divider("qspi1_x1", "qspi1_x2", CCM_CSCDR3, 11, 1);
+	clk[VF610_CLK_QSPI1] = imx_clk_gate2("qspi1", "qspi1_x1", CCM_CCGR8, CCM_CCGRx_CGn(4));
+
+	clk[VF610_CLK_ENET_50M] = imx_clk_fixed_factor("enet_50m", "pll5_enet", 1, 10);
+	clk[VF610_CLK_ENET_25M] = imx_clk_fixed_factor("enet_25m", "pll5_enet", 1, 20);
+	clk[VF610_CLK_ENET_SEL] = imx_clk_mux("enet_sel", CCM_CSCMR2, 4, 2, rmii_sels, 4);
+	clk[VF610_CLK_ENET_TS_SEL] = imx_clk_mux("enet_ts_sel", CCM_CSCMR2, 0, 3, enet_ts_sels, 7);
+	clk[VF610_CLK_ENET] = imx_clk_gate("enet", "enet_sel", CCM_CSCDR1, 24);
+	clk[VF610_CLK_ENET_TS] = imx_clk_gate("enet_ts", "enet_ts_sel", CCM_CSCDR1, 23);
+	clk[VF610_CLK_ENET0] = imx_clk_gate2("enet0", "ipg_bus", CCM_CCGR9, CCM_CCGRx_CGn(0));
+	clk[VF610_CLK_ENET1] = imx_clk_gate2("enet1", "ipg_bus", CCM_CCGR9, CCM_CCGRx_CGn(1));
+
+	clk[VF610_CLK_PIT] = imx_clk_gate2("pit", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(7));
+
+	clk[VF610_CLK_UART0] = imx_clk_gate2_cgr("uart0", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(7), 0x2);
+	clk[VF610_CLK_UART1] = imx_clk_gate2_cgr("uart1", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(8), 0x2);
+	clk[VF610_CLK_UART2] = imx_clk_gate2_cgr("uart2", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(9), 0x2);
+	clk[VF610_CLK_UART3] = imx_clk_gate2_cgr("uart3", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(10), 0x2);
+	clk[VF610_CLK_UART4] = imx_clk_gate2_cgr("uart4", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(9), 0x2);
+	clk[VF610_CLK_UART5] = imx_clk_gate2_cgr("uart5", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(10), 0x2);
+
+	clk[VF610_CLK_I2C0] = imx_clk_gate2("i2c0", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(6));
+	clk[VF610_CLK_I2C1] = imx_clk_gate2("i2c1", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(7));
+	clk[VF610_CLK_I2C2] = imx_clk_gate2("i2c2", "ipg_bus", CCM_CCGR10, CCM_CCGRx_CGn(6));
+	clk[VF610_CLK_I2C3] = imx_clk_gate2("i2c3", "ipg_bus", CCM_CCGR10, CCM_CCGRx_CGn(7));
+
+	clk[VF610_CLK_DSPI0] = imx_clk_gate2("dspi0", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(12));
+	clk[VF610_CLK_DSPI1] = imx_clk_gate2("dspi1", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(13));
+	clk[VF610_CLK_DSPI2] = imx_clk_gate2("dspi2", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(12));
+	clk[VF610_CLK_DSPI3] = imx_clk_gate2("dspi3", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(13));
+
+	clk[VF610_CLK_WDT] = imx_clk_gate2("wdt", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(14));
+
+	clk[VF610_CLK_ESDHC0_SEL] = imx_clk_mux("esdhc0_sel", CCM_CSCMR1, 16, 2, esdhc_sels, 4);
+	clk[VF610_CLK_ESDHC0_EN] = imx_clk_gate("esdhc0_en", "esdhc0_sel", CCM_CSCDR2, 28);
+	clk[VF610_CLK_ESDHC0_DIV] = imx_clk_divider("esdhc0_div", "esdhc0_en", CCM_CSCDR2, 16, 4);
+	clk[VF610_CLK_ESDHC0] = imx_clk_gate2("eshc0", "esdhc0_div", CCM_CCGR7, CCM_CCGRx_CGn(1));
+
+	clk[VF610_CLK_ESDHC1_SEL] = imx_clk_mux("esdhc1_sel", CCM_CSCMR1, 18, 2, esdhc_sels, 4);
+	clk[VF610_CLK_ESDHC1_EN] = imx_clk_gate("esdhc1_en", "esdhc1_sel", CCM_CSCDR2, 29);
+	clk[VF610_CLK_ESDHC1_DIV] = imx_clk_divider("esdhc1_div", "esdhc1_en", CCM_CSCDR2, 20, 4);
+	clk[VF610_CLK_ESDHC1] = imx_clk_gate2("eshc1", "esdhc1_div", CCM_CCGR7, CCM_CCGRx_CGn(2));
+
+	/*
+	 * ftm_ext_clk and ftm_fix_clk are FTM timer counter's
+	 * selectable clock sources, both use a common enable bit
+	 * in CCM_CSCDR1, selecting "dummy" clock as parent of
+	 * "ftm0_ext_fix" make it serve only for enable/disable.
+	 */
+	clk[VF610_CLK_FTM0_EXT_SEL] = imx_clk_mux("ftm0_ext_sel", CCM_CSCMR2, 6, 2, ftm_ext_sels, 4);
+	clk[VF610_CLK_FTM0_FIX_SEL] = imx_clk_mux("ftm0_fix_sel", CCM_CSCMR2, 14, 1, ftm_fix_sels, 2);
+	clk[VF610_CLK_FTM0_EXT_FIX_EN] = imx_clk_gate("ftm0_ext_fix_en", "dummy", CCM_CSCDR1, 25);
+	clk[VF610_CLK_FTM1_EXT_SEL] = imx_clk_mux("ftm1_ext_sel", CCM_CSCMR2, 8, 2, ftm_ext_sels, 4);
+	clk[VF610_CLK_FTM1_FIX_SEL] = imx_clk_mux("ftm1_fix_sel", CCM_CSCMR2, 15, 1, ftm_fix_sels, 2);
+	clk[VF610_CLK_FTM1_EXT_FIX_EN] = imx_clk_gate("ftm1_ext_fix_en", "dummy", CCM_CSCDR1, 26);
+	clk[VF610_CLK_FTM2_EXT_SEL] = imx_clk_mux("ftm2_ext_sel", CCM_CSCMR2, 10, 2, ftm_ext_sels, 4);
+	clk[VF610_CLK_FTM2_FIX_SEL] = imx_clk_mux("ftm2_fix_sel", CCM_CSCMR2, 16, 1, ftm_fix_sels, 2);
+	clk[VF610_CLK_FTM2_EXT_FIX_EN] = imx_clk_gate("ftm2_ext_fix_en", "dummy", CCM_CSCDR1, 27);
+	clk[VF610_CLK_FTM3_EXT_SEL] = imx_clk_mux("ftm3_ext_sel", CCM_CSCMR2, 12, 2, ftm_ext_sels, 4);
+	clk[VF610_CLK_FTM3_FIX_SEL] = imx_clk_mux("ftm3_fix_sel", CCM_CSCMR2, 17, 1, ftm_fix_sels, 2);
+	clk[VF610_CLK_FTM3_EXT_FIX_EN] = imx_clk_gate("ftm3_ext_fix_en", "dummy", CCM_CSCDR1, 28);
+
+	/* ftm(n)_clk are FTM module operation clock */
+	clk[VF610_CLK_FTM0] = imx_clk_gate2("ftm0", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(8));
+	clk[VF610_CLK_FTM1] = imx_clk_gate2("ftm1", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(9));
+	clk[VF610_CLK_FTM2] = imx_clk_gate2("ftm2", "ipg_bus", CCM_CCGR7, CCM_CCGRx_CGn(8));
+	clk[VF610_CLK_FTM3] = imx_clk_gate2("ftm3", "ipg_bus", CCM_CCGR7, CCM_CCGRx_CGn(9));
+
+	clk[VF610_CLK_DCU0_SEL] = imx_clk_mux("dcu0_sel", CCM_CSCMR1, 28, 1, dcu_sels, 2);
+	clk[VF610_CLK_DCU0_EN] = imx_clk_gate("dcu0_en", "dcu0_sel", CCM_CSCDR3, 19);
+	clk[VF610_CLK_DCU0_DIV] = imx_clk_divider("dcu0_div", "dcu0_en", CCM_CSCDR3, 16, 3);
+	clk[VF610_CLK_DCU0] = imx_clk_gate2("dcu0", "ipg_bus", CCM_CCGR3, CCM_CCGRx_CGn(8));
+	clk[VF610_CLK_DCU1_SEL] = imx_clk_mux("dcu1_sel", CCM_CSCMR1, 29, 1, dcu_sels, 2);
+	clk[VF610_CLK_DCU1_EN] = imx_clk_gate("dcu1_en", "dcu1_sel", CCM_CSCDR3, 23);
+	clk[VF610_CLK_DCU1_DIV] = imx_clk_divider("dcu1_div", "dcu1_en", CCM_CSCDR3, 20, 3);
+	clk[VF610_CLK_DCU1] = imx_clk_gate2("dcu1", "ipg_bus", CCM_CCGR9, CCM_CCGRx_CGn(8));
+
+	clk[VF610_CLK_TCON0] = imx_clk_gate2("tcon0", "platform_bus", CCM_CCGR1, CCM_CCGRx_CGn(13));
+	clk[VF610_CLK_TCON1] = imx_clk_gate2("tcon1", "platform_bus", CCM_CCGR7, CCM_CCGRx_CGn(13));
+
+	clk[VF610_CLK_ESAI_SEL] = imx_clk_mux("esai_sel", CCM_CSCMR1, 20, 2, esai_sels, 4);
+	clk[VF610_CLK_ESAI_EN] = imx_clk_gate("esai_en", "esai_sel", CCM_CSCDR2, 30);
+	clk[VF610_CLK_ESAI_DIV] = imx_clk_divider("esai_div", "esai_en", CCM_CSCDR2, 24, 4);
+	clk[VF610_CLK_ESAI] = imx_clk_gate2("esai", "esai_div", CCM_CCGR4, CCM_CCGRx_CGn(2));
+
+	clk[VF610_CLK_SAI0_SEL] = imx_clk_mux("sai0_sel", CCM_CSCMR1, 0, 2, sai_sels, 4);
+	clk[VF610_CLK_SAI0_EN] = imx_clk_gate("sai0_en", "sai0_sel", CCM_CSCDR1, 16);
+	clk[VF610_CLK_SAI0_DIV] = imx_clk_divider("sai0_div", "sai0_en", CCM_CSCDR1, 0, 4);
+	clk[VF610_CLK_SAI0] = imx_clk_gate2("sai0", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(15));
+
+	clk[VF610_CLK_SAI1_SEL] = imx_clk_mux("sai1_sel", CCM_CSCMR1, 2, 2, sai_sels, 4);
+	clk[VF610_CLK_SAI1_EN] = imx_clk_gate("sai1_en", "sai1_sel", CCM_CSCDR1, 17);
+	clk[VF610_CLK_SAI1_DIV] = imx_clk_divider("sai1_div", "sai1_en", CCM_CSCDR1, 4, 4);
+	clk[VF610_CLK_SAI1] = imx_clk_gate2("sai1", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(0));
+
+	clk[VF610_CLK_SAI2_SEL] = imx_clk_mux("sai2_sel", CCM_CSCMR1, 4, 2, sai_sels, 4);
+	clk[VF610_CLK_SAI2_EN] = imx_clk_gate("sai2_en", "sai2_sel", CCM_CSCDR1, 18);
+	clk[VF610_CLK_SAI2_DIV] = imx_clk_divider("sai2_div", "sai2_en", CCM_CSCDR1, 8, 4);
+	clk[VF610_CLK_SAI2] = imx_clk_gate2("sai2", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(1));
+
+	clk[VF610_CLK_SAI3_SEL] = imx_clk_mux("sai3_sel", CCM_CSCMR1, 6, 2, sai_sels, 4);
+	clk[VF610_CLK_SAI3_EN] = imx_clk_gate("sai3_en", "sai3_sel", CCM_CSCDR1, 19);
+	clk[VF610_CLK_SAI3_DIV] = imx_clk_divider("sai3_div", "sai3_en", CCM_CSCDR1, 12, 4);
+	clk[VF610_CLK_SAI3] = imx_clk_gate2("sai3", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(2));
+
+	clk[VF610_CLK_NFC_SEL] = imx_clk_mux("nfc_sel", CCM_CSCMR1, 12, 2, nfc_sels, 4);
+	clk[VF610_CLK_NFC_EN] = imx_clk_gate("nfc_en", "nfc_sel", CCM_CSCDR2, 9);
+	clk[VF610_CLK_NFC_PRE_DIV] = imx_clk_divider("nfc_pre_div", "nfc_en", CCM_CSCDR3, 13, 3);
+	clk[VF610_CLK_NFC_FRAC_DIV] = imx_clk_divider("nfc_frac_div", "nfc_pre_div", CCM_CSCDR2, 4, 4);
+	clk[VF610_CLK_NFC] = imx_clk_gate2("nfc", "nfc_frac_div", CCM_CCGR10, CCM_CCGRx_CGn(0));
+
+	clk[VF610_CLK_GPU_SEL] = imx_clk_mux("gpu_sel", CCM_CSCMR1, 14, 1, gpu_sels, 2);
+	clk[VF610_CLK_GPU_EN] = imx_clk_gate("gpu_en", "gpu_sel", CCM_CSCDR2, 10);
+	clk[VF610_CLK_GPU2D] = imx_clk_gate2("gpu", "gpu_en", CCM_CCGR8, CCM_CCGRx_CGn(15));
+
+	clk[VF610_CLK_VADC_SEL] = imx_clk_mux("vadc_sel", CCM_CSCMR1, 8, 2, vadc_sels, 3);
+	clk[VF610_CLK_VADC_EN] = imx_clk_gate("vadc_en", "vadc_sel", CCM_CSCDR1, 22);
+	clk[VF610_CLK_VADC_DIV] = imx_clk_divider("vadc_div", "vadc_en", CCM_CSCDR1, 20, 2);
+	clk[VF610_CLK_VADC_DIV_HALF] = imx_clk_fixed_factor("vadc_div_half", "vadc_div", 1, 2);
+	clk[VF610_CLK_VADC] = imx_clk_gate2("vadc", "vadc_div", CCM_CCGR8, CCM_CCGRx_CGn(7));
+
+	clk[VF610_CLK_ADC0] = imx_clk_gate2("adc0", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(11));
+	clk[VF610_CLK_ADC1] = imx_clk_gate2("adc1", "ipg_bus", CCM_CCGR7, CCM_CCGRx_CGn(11));
+	clk[VF610_CLK_DAC0] = imx_clk_gate2("dac0", "ipg_bus", CCM_CCGR8, CCM_CCGRx_CGn(12));
+	clk[VF610_CLK_DAC1] = imx_clk_gate2("dac1", "ipg_bus", CCM_CCGR8, CCM_CCGRx_CGn(13));
+
+	clk[VF610_CLK_ASRC] = imx_clk_gate2("asrc", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(1));
+
+	clk[VF610_CLK_FLEXCAN0_EN] = imx_clk_gate("flexcan0_en", "ipg_bus", CCM_CSCDR2, 11);
+	clk[VF610_CLK_FLEXCAN0] = imx_clk_gate2("flexcan0", "flexcan0_en", CCM_CCGR0, CCM_CCGRx_CGn(0));
+	clk[VF610_CLK_FLEXCAN1_EN] = imx_clk_gate("flexcan1_en", "ipg_bus", CCM_CSCDR2, 12);
+	clk[VF610_CLK_FLEXCAN1] = imx_clk_gate2("flexcan1", "flexcan1_en", CCM_CCGR9, CCM_CCGRx_CGn(4));
+
+	clk[VF610_CLK_DMAMUX0] = imx_clk_gate2("dmamux0", "platform_bus", CCM_CCGR0, CCM_CCGRx_CGn(4));
+	clk[VF610_CLK_DMAMUX1] = imx_clk_gate2("dmamux1", "platform_bus", CCM_CCGR0, CCM_CCGRx_CGn(5));
+	clk[VF610_CLK_DMAMUX2] = imx_clk_gate2("dmamux2", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(1));
+	clk[VF610_CLK_DMAMUX3] = imx_clk_gate2("dmamux3", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(2));
+
+	clk[VF610_CLK_SNVS] = imx_clk_gate2("snvs-rtc", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(7));
+	clk[VF610_CLK_DAP] = imx_clk_gate("dap", "platform_bus", CCM_CCSR, 24);
+	clk[VF610_CLK_OCOTP] = imx_clk_gate("ocotp", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(5));
+
+	imx_check_clocks(clk, ARRAY_SIZE(clk));
+
+	clk_set_parent(clk[VF610_CLK_QSPI0_SEL], clk[VF610_CLK_PLL1_PFD4]);
+	clk_set_rate(clk[VF610_CLK_QSPI0_X4_DIV], clk_get_rate(clk[VF610_CLK_QSPI0_SEL]) / 2);
+	clk_set_rate(clk[VF610_CLK_QSPI0_X2_DIV], clk_get_rate(clk[VF610_CLK_QSPI0_X4_DIV]) / 2);
+	clk_set_rate(clk[VF610_CLK_QSPI0_X1_DIV], clk_get_rate(clk[VF610_CLK_QSPI0_X2_DIV]) / 2);
+
+	clk_set_parent(clk[VF610_CLK_QSPI1_SEL], clk[VF610_CLK_PLL1_PFD4]);
+	clk_set_rate(clk[VF610_CLK_QSPI1_X4_DIV], clk_get_rate(clk[VF610_CLK_QSPI1_SEL]) / 2);
+	clk_set_rate(clk[VF610_CLK_QSPI1_X2_DIV], clk_get_rate(clk[VF610_CLK_QSPI1_X4_DIV]) / 2);
+	clk_set_rate(clk[VF610_CLK_QSPI1_X1_DIV], clk_get_rate(clk[VF610_CLK_QSPI1_X2_DIV]) / 2);
+
+	clk_set_parent(clk[VF610_CLK_ESDHC1_SEL], clk[VF610_CLK_PLL1_PFD3]);
+	clk_set_rate(clk[VF610_CLK_ESDHC1_DIV], clk_get_rate(clk[VF610_CLK_PLL1_PFD3]) / 9);
+
+	clk_set_parent(clk[VF610_CLK_SAI0_SEL], clk[VF610_CLK_AUDIO_EXT]);
+	clk_set_parent(clk[VF610_CLK_SAI1_SEL], clk[VF610_CLK_AUDIO_EXT]);
+	clk_set_parent(clk[VF610_CLK_SAI2_SEL], clk[VF610_CLK_AUDIO_EXT]);
+	clk_set_parent(clk[VF610_CLK_SAI3_SEL], clk[VF610_CLK_AUDIO_EXT]);
+
+	for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
+		clk_enable(clk[clks_init_on[i]]);
+
+	/* Add the clocks to provider list */
+	clk_data.clks = clk;
+	clk_data.clk_num = ARRAY_SIZE(clk);
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
+CLK_OF_DECLARE(vf610, "fsl,vf610-ccm", vf610_clocks_init);
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 26/28] i.MX: fec: Enable all clocks specified for FEC
From: Andrey Smirnov @ 2016-11-09 16:14 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

For some i.MX variants more than just "ipg" clock need to be enabled for
Ethernet to function, so change the code to enable all of the clock
defined for FEC node (this is what analogous Linux driver does as well).

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/net/fec_imx.c | 71 +++++++++++++++++++++++++++++++++++++++++++--------
 drivers/net/fec_imx.h | 10 +++++++-
 2 files changed, 70 insertions(+), 11 deletions(-)

diff --git a/drivers/net/fec_imx.c b/drivers/net/fec_imx.c
index 8bc7c29..1be5b9d 100644
--- a/drivers/net/fec_imx.c
+++ b/drivers/net/fec_imx.c
@@ -51,7 +51,7 @@ static int fec_miibus_read(struct mii_bus *bus, int phyAddr, int regAddr)
 	uint32_t phy;		/* convenient holder for the PHY */
 	uint64_t start;
 
-	writel(((clk_get_rate(fec->clk) >> 20) / 5) << 1,
+	writel(((clk_get_rate(fec->clk[FEC_CLK_IPG]) >> 20) / 5) << 1,
 			fec->regs + FEC_MII_SPEED);
 	/*
 	 * reading from any PHY's register is done by properly
@@ -94,7 +94,7 @@ static int fec_miibus_write(struct mii_bus *bus, int phyAddr,
 	uint32_t phy;		/* convenient holder for the PHY */
 	uint64_t start;
 
-	writel(((clk_get_rate(fec->clk) >> 20) / 5) << 1,
+	writel(((clk_get_rate(fec->clk[FEC_CLK_IPG]) >> 20) / 5) << 1,
 			fec->regs + FEC_MII_SPEED);
 
 	reg = regAddr << FEC_MII_DATA_RA_SHIFT;
@@ -287,7 +287,7 @@ static int fec_init(struct eth_device *dev)
 	 * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
 	 * and do not drop the Preamble.
 	 */
-	writel(((clk_get_rate(fec->clk) >> 20) / 5) << 1,
+	writel(((clk_get_rate(fec->clk[FEC_CLK_IPG]) >> 20) / 5) << 1,
 			fec->regs + FEC_MII_SPEED);
 
 	if (fec->interface == PHY_INTERFACE_MODE_RMII) {
@@ -651,6 +651,59 @@ static int fec_probe_dt(struct device_d *dev, struct fec_priv *fec)
 	return -ENODEV;
 }
 #endif
+
+static int fec_clk_enable(struct fec_priv *fec)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(fec->clk); i++) {
+		const int err = clk_enable(fec->clk[i]);
+		if (err < 0)
+			return err;
+	}
+
+	return 0;
+}
+
+static void fec_clk_disable(struct fec_priv *fec)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(fec->clk); i++) {
+		if (!IS_ERR_OR_NULL(fec->clk[i]))
+			clk_disable(fec->clk[i]);
+	}
+}
+
+static void fec_clk_put(struct fec_priv *fec)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(fec->clk); i++) {
+		if (!IS_ERR_OR_NULL(fec->clk[i]))
+			clk_put(fec->clk[i]);
+	}
+}
+
+static int fec_clk_get(struct fec_priv *fec)
+{
+	int i, err = 0;
+	static const char *clk_names[ARRAY_SIZE(fec->clk)] = {
+		"ipg", "ahb", "ptp"
+	};
+
+	for (i = 0; i < ARRAY_SIZE(fec->clk); i++) {
+		fec->clk[i] = clk_get(fec->edev.parent, clk_names[i]);
+		if (IS_ERR(fec->clk[i])) {
+			err = PTR_ERR(fec->clk[i]);
+			fec_clk_put(fec);
+			break;
+		}
+	}
+
+	return err;
+}
+
 static int fec_probe(struct device_d *dev)
 {
 	struct resource *iores;
@@ -681,13 +734,11 @@ static int fec_probe(struct device_d *dev)
 	edev->set_ethaddr = fec_set_hwaddr;
 	edev->parent = dev;
 
-	fec->clk = clk_get(dev, NULL);
-	if (IS_ERR(fec->clk)) {
-		ret = PTR_ERR(fec->clk);
+	ret = fec_clk_get(fec);
+	if (ret < 0)
 		goto err_free;
-	}
 
-	ret = clk_enable(fec->clk);
+	ret = fec_clk_enable(fec);
 	if (ret < 0)
 		goto put_clk;
 
@@ -787,9 +838,9 @@ free_gpio:
 release_res:
 	release_region(iores);
 disable_clk:
-	clk_disable(fec->clk);
+	fec_clk_disable(fec);
 put_clk:
-	clk_put(fec->clk);
+	fec_clk_put(fec);
 err_free:
 	free(fec);
 	return ret;
diff --git a/drivers/net/fec_imx.h b/drivers/net/fec_imx.h
index 1947e60..85d51ba 100644
--- a/drivers/net/fec_imx.h
+++ b/drivers/net/fec_imx.h
@@ -129,6 +129,14 @@ enum fec_type {
 	FEC_TYPE_IMX6,
 };
 
+enum fec_clock {
+	FEC_CLK_IPG,
+	FEC_CLK_AHB,
+	FEC_CLK_PTP,
+
+	FEC_CLK_NUM
+};
+
 /**
  * @brief i.MX27-FEC private structure
  */
@@ -144,7 +152,7 @@ struct fec_priv {
 	u32 phy_flags;
 	struct mii_bus miibus;
 	void (*phy_init)(struct phy_device *dev);
-	struct clk *clk;
+	struct clk *clk[FEC_CLK_NUM];
 	enum fec_type type;
 };
 
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 25/28] i.MX: ocotp: Add Vybrid support
From: Andrey Smirnov @ 2016-11-09 16:14 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 arch/arm/mach-imx/ocotp.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/arch/arm/mach-imx/ocotp.c b/arch/arm/mach-imx/ocotp.c
index b978508..989a3cc 100644
--- a/arch/arm/mach-imx/ocotp.c
+++ b/arch/arm/mach-imx/ocotp.c
@@ -451,6 +451,14 @@ static u32 imx6q_addr_to_offset(u32 addr)
 	return imx6sl_addr_to_offset(addr) + addendum;
 }
 
+static u32 vf610_addr_to_offset(u32 addr)
+{
+	if (addr == 0x04)
+		return 0x450;
+	else
+		return imx6q_addr_to_offset(addr);
+}
+
 static struct imx_ocotp_data imx6q_ocotp_data = {
 	.num_regs = 512,
 	.addr_to_offset = imx6q_addr_to_offset,
@@ -461,6 +469,11 @@ static struct imx_ocotp_data imx6sl_ocotp_data = {
 	.addr_to_offset = imx6sl_addr_to_offset,
 };
 
+static struct imx_ocotp_data vf610_ocotp_data = {
+	.num_regs = 512,
+	.addr_to_offset = vf610_addr_to_offset,
+};
+
 static __maybe_unused struct of_device_id imx_ocotp_dt_ids[] = {
 	{
 		.compatible = "fsl,imx6q-ocotp",
@@ -472,6 +485,9 @@ static __maybe_unused struct of_device_id imx_ocotp_dt_ids[] = {
 		.compatible = "fsl,imx6sl-ocotp",
 		.data = &imx6sl_ocotp_data,
 	}, {
+		.compatible = "fsl,vf610-ocotp",
+		.data = &vf610_ocotp_data,
+	}, {
 		/* sentinel */
 	}
 };
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 19/28] i.MX: i2c: Add Vybrid support
From: Andrey Smirnov @ 2016-11-09 16:14 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/i2c/busses/i2c-imx.c | 175 ++++++++++++++++++++++++++++++++++---------
 1 file changed, 138 insertions(+), 37 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index ec40475..ee0cfcc 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -43,6 +43,7 @@
 #include <linux/err.h>
 #include <pinctrl.h>
 #include <of_gpio.h>
+#include <of_device.h>
 
 #include <io.h>
 #include <i2c/i2c.h>
@@ -54,14 +55,25 @@
 /* Default value */
 #define FSL_I2C_BIT_RATE	100000	/* 100kHz */
 
-/* FSL I2C registers */
+/* IMX I2C registers:
+ * the I2C register offset is different between SoCs,
+ * to provid support for all these chips, split the
+ * register offset into a fixed base address and a
+ * variable shift value, then the full register offset
+ * will be calculated by
+ * reg_off = ( reg_base_addr << reg_shift)
+ */
 #define FSL_I2C_IADR	0x00	/* i2c slave address */
-#define FSL_I2C_IFDR	0x04	/* i2c frequency divider */
-#define FSL_I2C_I2CR	0x08	/* i2c control */
-#define FSL_I2C_I2SR	0x0C	/* i2c status */
-#define FSL_I2C_I2DR	0x10	/* i2c transfer data */
+#define FSL_I2C_IFDR	0x01	/* i2c frequency divider */
+#define FSL_I2C_I2CR	0x02	/* i2c control */
+#define FSL_I2C_I2SR	0x03	/* i2c status */
+#define FSL_I2C_I2DR	0x04	/* i2c transfer data */
 #define FSL_I2C_DFSRR	0x14	/* i2c digital filter sampling rate */
 
+#define IMX_I2C_REGSHIFT	2
+#define VF610_I2C_REGSHIFT	0
+
+
 /* Bits of FSL I2C registers */
 #define I2SR_RXAK	0x01
 #define I2SR_IIF	0x02
@@ -77,6 +89,22 @@
 #define I2CR_IIEN	0x40
 #define I2CR_IEN	0x80
 
+/* register bits different operating codes definition:
+ * 1) I2SR: Interrupt flags clear operation differ between SoCs:
+ * - write zero to clear(w0c) INT flag on i.MX,
+ * - but write one to clear(w1c) INT flag on Vybrid.
+ * 2) I2CR: I2C module enable operation also differ between SoCs:
+ * - set I2CR_IEN bit enable the module on i.MX,
+ * - but clear I2CR_IEN bit enable the module on Vybrid.
+ */
+#define I2SR_CLR_OPCODE_W0C	0x0
+#define I2SR_CLR_OPCODE_W1C	(I2SR_IAL | I2SR_IIF)
+#define I2CR_IEN_OPCODE_0	0x0
+#define I2CR_IEN_OPCODE_1	I2CR_IEN
+
+#define I2C_PM_TIMEOUT		10 /* ms */
+
+
 /*
  * sorted list of clock divider, register value pairs
  * taken from table 26-5, p.26-9, Freescale i.MX
@@ -85,8 +113,14 @@
  *
  * Duplicated divider values removed from list
  */
+struct fsl_i2c_clk_pair {
+	u16	div;
+	u16	val;
+};
+
 #ifndef CONFIG_PPC
-static u16 i2c_clk_div[50][2] = {
+
+static struct fsl_i2c_clk_pair imx_i2c_clk_div[] = {
 	{ 22,	0x20 }, { 24,	0x21 }, { 26,	0x22 }, { 28,	0x23 },
 	{ 30,	0x00 },	{ 32,	0x24 }, { 36,	0x25 }, { 40,	0x26 },
 	{ 42,	0x03 }, { 44,	0x27 },	{ 48,	0x28 }, { 52,	0x05 },
@@ -101,8 +135,36 @@ static u16 i2c_clk_div[50][2] = {
 	{ 1920,	0x1B },	{ 2048,	0x3F }, { 2304,	0x1C }, { 2560,	0x1D },
 	{ 3072,	0x1E }, { 3840,	0x1F }
 };
+
+/* Vybrid VF610 clock divider, register value pairs */
+static struct fsl_i2c_clk_pair vf610_i2c_clk_div[] = {
+	{ 20,   0x00 }, { 22,   0x01 }, { 24,   0x02 }, { 26,   0x03 },
+	{ 28,   0x04 }, { 30,   0x05 }, { 32,   0x09 }, { 34,   0x06 },
+	{ 36,   0x0A }, { 40,   0x07 }, { 44,   0x0C }, { 48,   0x0D },
+	{ 52,   0x43 }, { 56,   0x0E }, { 60,   0x45 }, { 64,   0x12 },
+	{ 68,   0x0F }, { 72,   0x13 }, { 80,   0x14 }, { 88,   0x15 },
+	{ 96,   0x19 }, { 104,  0x16 }, { 112,  0x1A }, { 128,  0x17 },
+	{ 136,  0x4F }, { 144,  0x1C }, { 160,  0x1D }, { 176,  0x55 },
+	{ 192,  0x1E }, { 208,  0x56 }, { 224,  0x22 }, { 228,  0x24 },
+	{ 240,  0x1F }, { 256,  0x23 }, { 288,  0x5C }, { 320,  0x25 },
+	{ 384,  0x26 }, { 448,  0x2A }, { 480,  0x27 }, { 512,  0x2B },
+	{ 576,  0x2C }, { 640,  0x2D }, { 768,  0x31 }, { 896,  0x32 },
+	{ 960,  0x2F }, { 1024, 0x33 }, { 1152, 0x34 }, { 1280, 0x35 },
+	{ 1536, 0x36 }, { 1792, 0x3A }, { 1920, 0x37 }, { 2048, 0x3B },
+	{ 2304, 0x3C }, { 2560, 0x3D }, { 3072, 0x3E }, { 3584, 0x7A },
+	{ 3840, 0x3F }, { 4096, 0x7B }, { 5120, 0x7D }, { 6144, 0x7E },
+};
+
 #endif
 
+struct fsl_i2c_hwdata {
+	unsigned		regshift;
+	struct fsl_i2c_clk_pair	*clk_div;
+	unsigned		ndivs;
+	unsigned		i2sr_clr_opcode;
+	unsigned		i2cr_ien_opcode;
+};
+
 struct fsl_i2c_struct {
 	void __iomem		*base;
 	struct clk		*clk;
@@ -112,6 +174,7 @@ struct fsl_i2c_struct {
 	unsigned int		ifdr;	/* FSL_I2C_IFDR */
 	unsigned int		dfsrr;  /* FSL_I2C_DFSRR */
 	struct i2c_bus_recovery_info rinfo;
+	const struct fsl_i2c_hwdata *hwdata;
 };
 #define to_fsl_i2c_struct(a)	container_of(a, struct fsl_i2c_struct, adapter)
 
@@ -119,12 +182,14 @@ static inline void fsl_i2c_write_reg(unsigned int val,
 				     struct fsl_i2c_struct *i2c_fsl,
 				     unsigned int reg)
 {
+	reg <<= i2c_fsl->hwdata->regshift;
 	writeb(val, i2c_fsl->base + reg);
 }
 
 static inline unsigned char fsl_i2c_read_reg(struct fsl_i2c_struct *i2c_fsl,
 					     unsigned int reg)
 {
+	reg <<= i2c_fsl->hwdata->regshift;
 	return readb(i2c_fsl->base + reg);
 }
 
@@ -198,7 +263,9 @@ static int i2c_fsl_trx_complete(struct i2c_adapter *adapter)
 			return -EIO;
 		}
 	}
-	fsl_i2c_write_reg(0, i2c_fsl, FSL_I2C_I2SR);
+
+	fsl_i2c_write_reg(i2c_fsl->hwdata->i2sr_clr_opcode,
+			  i2c_fsl, FSL_I2C_I2SR);
 
 	return 0;
 }
@@ -229,13 +296,17 @@ static int i2c_fsl_start(struct i2c_adapter *adapter)
 	unsigned int temp = 0;
 	int result;
 
-	fsl_i2c_write_reg(i2c_fsl->ifdr, fsl_i2c, FSL_I2C_IFDR);
+	fsl_i2c_write_reg(i2c_fsl->ifdr, i2c_fsl, FSL_I2C_IFDR);
+#ifdef CONFIG_PPC
 	if (i2c_fsl->dfsrr != -1)
 		fsl_i2c_write_reg(i2c_fsl->dfsrr, fsl_i2c, FSL_I2C_DFSRR);
+#endif
 
 	/* Enable I2C controller */
-	fsl_i2c_write_reg(0, fsl_i2c, FSL_I2C_I2SR);
-	fsl_i2c_write_reg(I2CR_IEN, fsl_i2c, FSL_I2C_I2CR);
+	fsl_i2c_write_reg(i2c_fsl->hwdata->i2sr_clr_opcode,
+			  i2c_fsl, FSL_I2C_I2SR);
+	fsl_i2c_write_reg(i2c_fsl->hwdata->i2cr_ien_opcode,
+			  i2c_fsl, FSL_I2C_I2CR);
 
 	/* Wait controller to be stable */
 	udelay(100);
@@ -243,7 +314,7 @@ static int i2c_fsl_start(struct i2c_adapter *adapter)
 	/* Start I2C transaction */
 	temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2CR);
 	temp |= I2CR_MSTA;
-	fsl_i2c_write_reg(temp, fsl_i2c, FSL_I2C_I2CR);
+	fsl_i2c_write_reg(temp, i2c_fsl, FSL_I2C_I2CR);
 
 	result = i2c_fsl_bus_busy(adapter, 1);
 	if (result) {
@@ -256,7 +327,7 @@ static int i2c_fsl_start(struct i2c_adapter *adapter)
 	i2c_fsl->stopped = 0;
 
 	temp |= I2CR_MTX | I2CR_TXAK;
-	fsl_i2c_write_reg(temp, fsl_i2c, FSL_I2C_I2CR);
+	fsl_i2c_write_reg(temp, i2c_fsl, FSL_I2C_I2CR);
 
 	return result;
 }
@@ -270,7 +341,7 @@ static void i2c_fsl_stop(struct i2c_adapter *adapter)
 		/* Stop I2C transaction */
 		temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2CR);
 		temp &= ~(I2CR_MSTA | I2CR_MTX);
-		fsl_i2c_write_reg(temp, fsl_i2c, FSL_I2C_I2CR);
+		fsl_i2c_write_reg(temp, i2c_fsl, FSL_I2C_I2CR);
 		/* wait for the stop condition to be send, otherwise the i2c
 		 * controller is disabled before the STOP is sent completely */
 		i2c_fsl->stopped = i2c_fsl_bus_busy(adapter, 0) ? 0 : 1;
@@ -282,7 +353,8 @@ static void i2c_fsl_stop(struct i2c_adapter *adapter)
 	}
 
 	/* Disable I2C controller, and force our state to stopped */
-	fsl_i2c_write_reg(0, fsl_i2c, FSL_I2C_I2CR);
+	temp = i2c_fsl->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
+	fsl_i2c_write_reg(temp, i2c_fsl, FSL_I2C_I2CR);
 }
 
 #ifdef CONFIG_PPC
@@ -356,6 +428,7 @@ static void i2c_fsl_set_clk(struct fsl_i2c_struct *i2c_fsl,
 static void i2c_fsl_set_clk(struct fsl_i2c_struct *i2c_fsl,
 			    unsigned int rate)
 {
+	struct fsl_i2c_clk_pair *i2c_clk_div = i2c_fsl->hwdata->clk_div;
 	unsigned int i2c_clk_rate;
 	unsigned int div;
 	int i;
@@ -363,16 +436,16 @@ static void i2c_fsl_set_clk(struct fsl_i2c_struct *i2c_fsl,
 	/* Divider value calculation */
 	i2c_clk_rate = clk_get_rate(i2c_fsl->clk);
 	div = (i2c_clk_rate + rate - 1) / rate;
-	if (div < i2c_clk_div[0][0])
+	if (div < i2c_clk_div[0].div)
 		i = 0;
-	else if (div > i2c_clk_div[ARRAY_SIZE(i2c_clk_div) - 1][0])
-		i = ARRAY_SIZE(i2c_clk_div) - 1;
+	else if (div > i2c_clk_div[i2c_fsl->hwdata->ndivs - 1].div)
+		i = i2c_clk_div[i2c_fsl->hwdata->ndivs - 1].div - 1;
 	else
-		for (i = 0; i2c_clk_div[i][0] < div; i++)
+		for (i = 0; i2c_clk_div[i].div < div; i++)
 			;
 
 	/* Store divider value */
-	i2c_fsl->ifdr = i2c_clk_div[i][1];
+	i2c_fsl->ifdr = i2c_clk_div[i].val;
 
 	/*
 	 * There dummy delay is calculated.
@@ -381,13 +454,13 @@ static void i2c_fsl_set_clk(struct fsl_i2c_struct *i2c_fsl,
 	 * to fix chip hardware bug.
 	 */
 	i2c_fsl->disable_delay =
-		(500000U * i2c_clk_div[i][0] + (i2c_clk_rate / 2) - 1) /
+		(500000U * i2c_clk_div[i].div + (i2c_clk_rate / 2) - 1) /
 		(i2c_clk_rate / 2);
 
 	dev_dbg(&i2c_fsl->adapter.dev, "<%s> I2C_CLK=%d, REQ DIV=%d\n",
 		__func__, i2c_clk_rate, div);
 	dev_dbg(&i2c_fsl->adapter.dev, "<%s> IFDR[IC]=0x%x, REAL DIV=%d\n",
-		__func__, i2c_clk_div[i][1], i2c_clk_div[i][0]);
+		__func__, i2c_clk_div[i].val, i2c_clk_div[i].div);
 }
 #endif
 
@@ -402,7 +475,8 @@ static int i2c_fsl_write(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 			__func__, msgs->addr << 1);
 
 		/* write slave address */
-		fsl_i2c_write_reg(msgs->addr << 1, fsl_i2c, FSL_I2C_I2DR);
+		fsl_i2c_write_reg(msgs->addr << 1, i2c_fsl,
+				  FSL_I2C_I2DR);
 
 		result = i2c_fsl_trx_complete(adapter);
 		if (result)
@@ -417,7 +491,8 @@ static int i2c_fsl_write(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 		dev_dbg(&adapter->dev,
 			"<%s> write byte: B%d=0x%02X\n",
 			__func__, i, msgs->buf[i]);
-		fsl_i2c_write_reg(msgs->buf[i], fsl_i2c, FSL_I2C_I2DR);
+		fsl_i2c_write_reg(msgs->buf[i], i2c_fsl,
+				  FSL_I2C_I2DR);
 
 		result = i2c_fsl_trx_complete(adapter);
 		if (result)
@@ -436,7 +511,8 @@ static int i2c_fsl_read(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 	unsigned int temp;
 
 	/* clear IIF */
-	fsl_i2c_write_reg(0x0, fsl_i2c, FSL_I2C_I2SR);
+	fsl_i2c_write_reg(i2c_fsl->hwdata->i2sr_clr_opcode,
+			  i2c_fsl, FSL_I2C_I2SR);
 
 	if ( !(msgs->flags & I2C_M_DATA_ONLY) ) {
 		dev_dbg(&adapter->dev,
@@ -444,7 +520,8 @@ static int i2c_fsl_read(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 			__func__, (msgs->addr << 1) | 0x01);
 
 		/* write slave address */
-		fsl_i2c_write_reg((msgs->addr << 1) | 0x01, fsl_i2c, FSL_I2C_I2DR);
+		fsl_i2c_write_reg((msgs->addr << 1) | 0x01, i2c_fsl,
+				  FSL_I2C_I2DR);
 
 		result = i2c_fsl_trx_complete(adapter);
 		if (result)
@@ -459,9 +536,9 @@ static int i2c_fsl_read(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 	temp &= ~I2CR_MTX;
 	if (msgs->len - 1)
 		temp &= ~I2CR_TXAK;
-	fsl_i2c_write_reg(temp, fsl_i2c, FSL_I2C_I2CR);
+	fsl_i2c_write_reg(temp, i2c_fsl, FSL_I2C_I2CR);
 
-	fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2DR);	/* dummy read */
+	fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2DR); /* dummy read */
 
 	/* read data */
 	for (i = 0; i < msgs->len; i++) {
@@ -476,7 +553,7 @@ static int i2c_fsl_read(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 			 */
 			temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2CR);
 			temp &= ~(I2CR_MSTA | I2CR_MTX);
-			fsl_i2c_write_reg(temp, fsl_i2c, FSL_I2C_I2CR);
+			fsl_i2c_write_reg(temp, i2c_fsl, FSL_I2C_I2CR);
 
 			/*
 			 * adding this delay helps on low bitrates
@@ -488,7 +565,7 @@ static int i2c_fsl_read(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 		} else if (i == (msgs->len - 2)) {
 			temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2CR);
 			temp |= I2CR_TXAK;
-			fsl_i2c_write_reg(temp, fsl_i2c, FSL_I2C_I2CR);
+			fsl_i2c_write_reg(temp, i2c_fsl, FSL_I2C_I2CR);
 		}
 		msgs->buf[i] = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2DR);
 
@@ -520,7 +597,7 @@ static int i2c_fsl_xfer(struct i2c_adapter *adapter,
 		if (i && !(msgs[i].flags & I2C_M_DATA_ONLY)) {
 			temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2CR);
 			temp |= I2CR_RSTA;
-			fsl_i2c_write_reg(temp, fsl_i2c, FSL_I2C_I2CR);
+			fsl_i2c_write_reg(temp, i2c_fsl, FSL_I2C_I2CR);
 
 			result = i2c_fsl_bus_busy(adapter, 1);
 			if (result)
@@ -604,6 +681,13 @@ static int __init i2c_fsl_probe(struct device_d *pdev)
 		goto fail;
 	}
 #endif
+
+	i2c_fsl->hwdata = of_device_get_match_data(pdev);
+	if (!i2c_fsl->hwdata) {
+		ret = -EINVAL;
+		goto fail;
+	}
+
 	/* Setup i2c_fsl driver structure */
 	i2c_fsl->adapter.master_xfer = i2c_fsl_xfer;
 	i2c_fsl->adapter.nr = pdev->id;
@@ -627,8 +711,9 @@ static int __init i2c_fsl_probe(struct device_d *pdev)
 		i2c_fsl_set_clk(i2c_fsl, FSL_I2C_BIT_RATE);
 
 	/* Set up chip registers to defaults */
-	fsl_i2c_write_reg(0, i2c_fsl, FSL_I2C_I2CR);
-	fsl_i2c_write_reg(0, i2c_fsl, FSL_I2C_I2SR);
+	fsl_i2c_write_reg(i2c_fsl->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
+			  i2c_fsl, FSL_I2C_I2CR);
+	fsl_i2c_write_reg(i2c_fsl->hwdata->i2sr_clr_opcode, i2c_fsl, FSL_I2C_I2SR);
 
 	/* Add I2C adapter */
 	ret = i2c_add_numbered_adapter(&i2c_fsl->adapter);
@@ -644,12 +729,28 @@ fail:
 	return ret;
 }
 
+static const struct fsl_i2c_hwdata imx21_i2c_hwdata = {
+	.regshift		= IMX_I2C_REGSHIFT,
+	.clk_div		= imx_i2c_clk_div,
+	.ndivs			= ARRAY_SIZE(imx_i2c_clk_div),
+	.i2sr_clr_opcode	= I2SR_CLR_OPCODE_W0C,
+	.i2cr_ien_opcode	= I2CR_IEN_OPCODE_1,
+
+};
+
+static const struct fsl_i2c_hwdata vf610_i2c_hwdata = {
+	.regshift		= VF610_I2C_REGSHIFT,
+	.clk_div		= vf610_i2c_clk_div,
+	.ndivs			= ARRAY_SIZE(vf610_i2c_clk_div),
+	.i2sr_clr_opcode	= I2SR_CLR_OPCODE_W1C,
+	.i2cr_ien_opcode	= I2CR_IEN_OPCODE_0,
+
+};
+
 static __maybe_unused struct of_device_id imx_i2c_dt_ids[] = {
-	{
-		.compatible = "fsl,imx21-i2c",
-	}, {
-		/* sentinel */
-	}
+	{ .compatible = "fsl,imx21-i2c", .data = &imx21_i2c_hwdata, },
+	{ .compatible = "fsl,vf610-i2c", .data = &vf610_i2c_hwdata, },
+	{ /* sentinel */ }
 };
 
 static struct driver_d i2c_fsl_driver = {
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 24/28] i.MX: ocotp: Account for shadow memory gaps
From: Andrey Smirnov @ 2016-11-09 16:14 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Shadow memory does not have a true 1:1 mapping to fuse address
space. All i.MX6 devices, with exception of i.MX6SL have a 0x100 byte
gap between banks 5 and 6 (or addresses 0x2f and 0x30), so we need to
account for that when reading data from shadow memory.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 arch/arm/mach-imx/ocotp.c | 34 +++++++++++++++++++++++++++++++---
 1 file changed, 31 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-imx/ocotp.c b/arch/arm/mach-imx/ocotp.c
index 44ee0b7..b978508 100644
--- a/arch/arm/mach-imx/ocotp.c
+++ b/arch/arm/mach-imx/ocotp.c
@@ -73,6 +73,7 @@
 
 struct imx_ocotp_data {
 	int num_regs;
+	u32 (*addr_to_offset)(u32 addr);
 };
 
 struct ocotp_priv {
@@ -84,6 +85,7 @@ struct ocotp_priv {
 	int sense_enable;
 	char ethaddr[6];
 	struct regmap_config map_config;
+	const struct imx_ocotp_data *data;
 };
 
 static int imx6_ocotp_set_timing(struct ocotp_priv *priv)
@@ -192,7 +194,8 @@ static int imx_ocotp_reg_read(void *ctx, unsigned int reg, unsigned int *val)
 		if (ret)
 			return ret;
 	} else {
-		*(u32 *)val = readl(priv->base + 0x400 + index * 0x10);
+		*(u32 *)val = readl(priv->base +
+				    priv->data->addr_to_offset(index));
 	}
 
 	return 0;
@@ -272,7 +275,8 @@ static int imx_ocotp_reg_write(void *ctx, unsigned int reg, unsigned int val)
 		if (ret < 0)
 			return ret;
 	} else {
-		writel(val, priv->base + 0x400 + index * 0x10);
+		writel(val, priv->base +
+		       priv->data->addr_to_offset(index));
 	}
 
 	if (priv->permanent_write_enable)
@@ -374,7 +378,7 @@ static int imx_ocotp_probe(struct device_d *dev)
 	void __iomem *base;
 	struct ocotp_priv *priv;
 	int ret = 0;
-	struct imx_ocotp_data *data;
+	const struct imx_ocotp_data *data;
 
 	ret = dev_get_drvdata(dev, (const void **)&data);
 	if (ret)
@@ -389,6 +393,7 @@ static int imx_ocotp_probe(struct device_d *dev)
 
 	priv = xzalloc(sizeof(*priv));
 
+	priv->data      = data;
 	priv->base	= base;
 	priv->clk	= clk_get(dev, NULL);
 	if (IS_ERR(priv->clk))
@@ -425,12 +430,35 @@ static int imx_ocotp_probe(struct device_d *dev)
 	return 0;
 }
 
+static u32 imx6sl_addr_to_offset(u32 addr)
+{
+	return 0x400 + addr * 0x10;
+}
+
+static u32 imx6q_addr_to_offset(u32 addr)
+{
+	u32 addendum = 0;
+
+	if (addr > 0x2F) {
+		/*
+		 * If we are reading past Bank 5, take into account a
+		 * 0x100 bytes wide gap between Bank 5 and Bank 6
+		 */
+		addendum += 0x100;
+	}
+
+
+	return imx6sl_addr_to_offset(addr) + addendum;
+}
+
 static struct imx_ocotp_data imx6q_ocotp_data = {
 	.num_regs = 512,
+	.addr_to_offset = imx6q_addr_to_offset,
 };
 
 static struct imx_ocotp_data imx6sl_ocotp_data = {
 	.num_regs = 256,
+	.addr_to_offset = imx6sl_addr_to_offset,
 };
 
 static __maybe_unused struct of_device_id imx_ocotp_dt_ids[] = {
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 28/28] gpio: Add GPIO driver for Vybrid
From: Andrey Smirnov @ 2016-11-09 16:14 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Add GPIO driver for VF610 Family of SoCs (based on analogous driver from
Linux kernel)

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/gpio/Kconfig      |   3 +
 drivers/gpio/Makefile     |   1 +
 drivers/gpio/gpio-vf610.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 185 insertions(+)
 create mode 100644 drivers/gpio/gpio-vf610.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index ab919c9..fe62778 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -49,6 +49,9 @@ config GPIO_GENERIC_PLATFORM
 config GPIO_IMX
 	def_bool ARCH_IMX
 
+config GPIO_VF610
+	def_bool ARCH_VF610
+
 config GPIO_MXS
 	def_bool ARCH_MXS
 
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 8767eed..248100f 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -18,3 +18,4 @@ obj-$(CONFIG_GPIO_PL061)	+= gpio-pl061.o
 obj-$(CONFIG_GPIO_STMPE)	+= gpio-stmpe.o
 obj-$(CONFIG_GPIO_TEGRA)	+= gpio-tegra.o
 obj-$(CONFIG_GPIO_DESIGNWARE)	+= gpio-dw.o
+obj-$(CONFIG_GPIO_VF610)	+= gpio-vf610.o
diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c
new file mode 100644
index 0000000..c82723f
--- /dev/null
+++ b/drivers/gpio/gpio-vf610.c
@@ -0,0 +1,181 @@
+/*
+ * vf610 GPIO support through PORT and GPIO module
+ *
+ * Copyright (c) 2014 Toradex AG.
+ *
+ * Author: Stefan Agner <stefan@agner.ch>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <io.h>
+#include <of.h>
+#include <gpio.h>
+#include <init.h>
+#include <pinctrl.h>
+
+#define VF610_GPIO_PER_PORT	32
+#define PINCTRL_BASE		2
+#define COUNT 3
+
+struct vf610_gpio_port {
+	struct gpio_chip chip;
+	void __iomem *gpio_base;
+	unsigned int pinctrl_base;
+};
+
+#define GPIO_PDOR		0x00
+#define GPIO_PSOR		0x04
+#define GPIO_PCOR		0x08
+#define GPIO_PTOR		0x0c
+#define GPIO_PDIR		0x10
+
+#define PORT_PCR(n)		((n) * 0x4)
+#define PORT_PCR_IRQC_OFFSET	16
+
+#define PORT_ISFR		0xa0
+#define PORT_DFER		0xc0
+#define PORT_DFCR		0xc4
+#define PORT_DFWR		0xc8
+
+#define PORT_INT_OFF		0x0
+#define PORT_INT_LOGIC_ZERO	0x8
+#define PORT_INT_RISING_EDGE	0x9
+#define PORT_INT_FALLING_EDGE	0xa
+#define PORT_INT_EITHER_EDGE	0xb
+#define PORT_INT_LOGIC_ONE	0xc
+
+static const struct of_device_id vf610_gpio_dt_ids[] = {
+	{ .compatible = "fsl,vf610-gpio" },
+	{ /* sentinel */ }
+};
+
+
+static int vf610_gpio_get_value(struct gpio_chip *chip, unsigned int gpio)
+{
+	struct vf610_gpio_port *port =
+		container_of(chip, struct vf610_gpio_port, chip);
+
+	return !!(readl(port->gpio_base + GPIO_PDIR) & BIT(gpio));
+}
+
+static void vf610_gpio_set_value(struct gpio_chip *chip,
+				  unsigned int gpio, int val)
+{
+	struct vf610_gpio_port *port =
+		container_of(chip, struct vf610_gpio_port, chip);
+	unsigned long mask = BIT(gpio);
+
+	writel(mask, port->gpio_base + ((val) ? GPIO_PSOR : GPIO_PCOR));
+}
+
+static int vf610_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+	struct vf610_gpio_port *port =
+		container_of(chip, struct vf610_gpio_port, chip);
+
+	return pinctrl_gpio_direction_input(port->pinctrl_base + gpio);
+}
+
+static int vf610_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
+				       int value)
+{
+	struct vf610_gpio_port *port =
+		container_of(chip, struct vf610_gpio_port, chip);
+
+	vf610_gpio_set_value(chip, gpio, value);
+
+	return pinctrl_gpio_direction_output(port->pinctrl_base + gpio);
+}
+
+static int vf610_gpio_get_direction(struct gpio_chip *chip, unsigned gpio)
+{
+	struct vf610_gpio_port *port =
+		container_of(chip, struct vf610_gpio_port, chip);
+
+	return pinctrl_gpio_get_direction(port->pinctrl_base + gpio);
+}
+
+static struct gpio_ops vf610_gpio_ops = {
+	.direction_input = vf610_gpio_direction_input,
+	.direction_output = vf610_gpio_direction_output,
+	.get = vf610_gpio_get_value,
+	.set = vf610_gpio_set_value,
+	.get_direction = vf610_gpio_get_direction,
+};
+
+static int vf610_gpio_probe(struct device_d *dev)
+{
+	int ret, size;
+	struct resource *iores;
+	struct vf610_gpio_port *port;
+	const __be32 *gpio_ranges;
+
+	port = xzalloc(sizeof(*port));
+	if (!port)
+		return -ENOMEM;
+
+	gpio_ranges = of_get_property(dev->device_node, "gpio-ranges", &size);
+	if (!gpio_ranges) {
+		dev_err(dev, "Couldn't read 'gpio-ranges' propery of %s\n",
+			dev->device_node->full_name);
+		ret = -EINVAL;
+		goto free_port;
+	}
+
+	port->pinctrl_base = be32_to_cpu(gpio_ranges[PINCTRL_BASE]);
+	port->chip.ngpio   = be32_to_cpu(gpio_ranges[COUNT]);
+
+	iores = dev_request_mem_resource(dev, 1);
+	if (IS_ERR(iores)) {
+		ret = PTR_ERR(iores);
+		dev_dbg(dev, "Failed to request memory resource\n");
+		goto free_port;
+	}
+
+	port->gpio_base = IOMEM(iores->start);
+
+	port->chip.ops  = &vf610_gpio_ops;
+	if (dev->id < 0) {
+		port->chip.base = of_alias_get_id(dev->device_node, "gpio");
+		if (port->chip.base < 0) {
+			ret = port->chip.base;
+			dev_dbg(dev, "Failed to get GPIO alias\n");
+			goto free_port;
+		}
+	} else {
+		port->chip.base = dev->id;
+	}
+
+
+	port->chip.base *= VF610_GPIO_PER_PORT;
+	port->chip.dev = dev;
+	gpiochip_add(&port->chip);
+
+	return 0;
+
+free_port:
+	free(port);
+	return ret;
+}
+
+static struct driver_d vf610_gpio_driver = {
+	.name	= "gpio-vf610",
+	.probe  = vf610_gpio_probe,
+	.of_compatible = DRV_OF_COMPAT(vf610_gpio_dt_ids),
+};
+
+static int __init gpio_vf610_init(void)
+{
+	return platform_driver_register(&vf610_gpio_driver);
+}
+core_initcall(gpio_vf610_init);
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 27/28] i.MX: fec: Add support for Vybrid variant
From: Andrey Smirnov @ 2016-11-09 16:14 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Add support for Vybrid variant of this IP block

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/net/fec_imx.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/fec_imx.c b/drivers/net/fec_imx.c
index 1be5b9d..e2b25fe 100644
--- a/drivers/net/fec_imx.c
+++ b/drivers/net/fec_imx.c
@@ -870,6 +870,9 @@ static __maybe_unused struct of_device_id imx_fec_dt_ids[] = {
 		.compatible = "fsl,imx6sx-fec",
 		.data = (void *)FEC_TYPE_IMX6,
 	}, {
+		.compatible = "fsl,mvf600-fec",
+		.data = (void *)FEC_TYPE_IMX6,
+	}, {
 		/* sentinel */
 	}
 };
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 23/28] i.MX: ocotp: Remove unused #define
From: Andrey Smirnov @ 2016-11-09 16:14 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 arch/arm/mach-imx/ocotp.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm/mach-imx/ocotp.c b/arch/arm/mach-imx/ocotp.c
index 17b944b..44ee0b7 100644
--- a/arch/arm/mach-imx/ocotp.c
+++ b/arch/arm/mach-imx/ocotp.c
@@ -66,7 +66,6 @@
 #define BF(value, field)		(((value) << field) & field##_MASK)
 
 /* Other definitions */
-#define FUSE_REGS_COUNT			(16 * 8)
 #define IMX6_OTP_DATA_ERROR_VAL		0xBADABADA
 #define DEF_RELAX			20
 #define MAC_OFFSET			(0x22 * 4)
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 21/28] i.MX: esdhc: Request "per" clock explicitly
From: Andrey Smirnov @ 2016-11-09 16:14 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Calling clk_get() with NULL as the second argument will give us "ipg"
clock as a result. The actual clock feeding into the peripheral is "per"
and, depending on the SoC, "ipg" and "per" may be separated by a clock
divider, so querying "ipg"'s rate may not result in rate that does not
represent the actual peripheral clock rate.

Change the code to request "per" as our peripheral clock to avoid
aforementioned problem.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/mci/imx-esdhc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c
index 764a106..d72e3f8 100644
--- a/drivers/mci/imx-esdhc.c
+++ b/drivers/mci/imx-esdhc.c
@@ -627,7 +627,7 @@ static int fsl_esdhc_probe(struct device_d *dev)
 	if (!host->socdata)
 		return -EINVAL;
 
-	host->clk = clk_get(dev, NULL);
+	host->clk = clk_get(dev, "per");
 	if (IS_ERR(host->clk))
 		return PTR_ERR(host->clk);
 
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 22/28] i.MX: Kconfig: Enable OCOTP on Vybrid
From: Andrey Smirnov @ 2016-11-09 16:14 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Enable OCOTP driver on Vybrid as well as i.MX6

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 arch/arm/mach-imx/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 5f4fdc6..24a123a 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -659,7 +659,7 @@ config IMX_IIM_FUSE_BLOW
 
 config IMX_OCOTP
 	tristate "i.MX6 On Chip OTP controller"
-	depends on ARCH_IMX6
+	depends on ARCH_IMX6 || ARCH_VF610
 	depends on OFDEVICE
 	help
 	  This adds support for the i.MX6 On-Chip OTP controller. Currently the
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 18/28] i.MX: i2c: Use read/write adapter functions
From: Andrey Smirnov @ 2016-11-09 16:14 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Use read/write adapter functions instead of directly calling to
readb/writeb. This is needed to prepare driver code to support Vybrid
SoC's variant of this block.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/i2c/busses/i2c-imx.c | 88 +++++++++++++++++++++++---------------------
 1 file changed, 46 insertions(+), 42 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index e407896..ec40475 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -115,14 +115,27 @@ struct fsl_i2c_struct {
 };
 #define to_fsl_i2c_struct(a)	container_of(a, struct fsl_i2c_struct, adapter)
 
+static inline void fsl_i2c_write_reg(unsigned int val,
+				     struct fsl_i2c_struct *i2c_fsl,
+				     unsigned int reg)
+{
+	writeb(val, i2c_fsl->base + reg);
+}
+
+static inline unsigned char fsl_i2c_read_reg(struct fsl_i2c_struct *i2c_fsl,
+					     unsigned int reg)
+{
+	return readb(i2c_fsl->base + reg);
+}
+
 #ifdef CONFIG_I2C_DEBUG
 static void i2c_fsl_dump_reg(struct i2c_adapter *adapter)
 {
 	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
 	u32 reg_cr, reg_sr;
 
-	reg_cr = readb(i2c_fsl->base + FSL_I2C_I2CR);
-	reg_sr = readb(i2c_fsl->base + FSL_I2C_I2SR);
+	reg_cr = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2CR);
+	reg_sr = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2SR);
 
 	dev_dbg(adapter->dev, "CONTROL:\t"
 		"IEN =%d, IIEN=%d, MSTA=%d, MTX =%d, TXAK=%d, RSTA=%d\n",
@@ -144,16 +157,16 @@ static inline void i2c_fsl_dump_reg(struct i2c_adapter *adapter)
 }
 #endif
 
+
 static int i2c_fsl_bus_busy(struct i2c_adapter *adapter, int for_busy)
 {
 	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
-	void __iomem *base = i2c_fsl->base;
 	uint64_t start;
 	unsigned int temp;
 
 	start = get_time_ns();
 	while (1) {
-		temp = readb(base + FSL_I2C_I2SR);
+		temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2SR);
 		if (for_busy && (temp & I2SR_IBB))
 			break;
 		if (!for_busy && !(temp & I2SR_IBB))
@@ -172,12 +185,11 @@ static int i2c_fsl_bus_busy(struct i2c_adapter *adapter, int for_busy)
 static int i2c_fsl_trx_complete(struct i2c_adapter *adapter)
 {
 	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
-	void __iomem *base = i2c_fsl->base;
 	uint64_t start;
 
 	start = get_time_ns();
 	while (1) {
-		unsigned int reg = readb(base + FSL_I2C_I2SR);
+		unsigned int reg = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2SR);
 		if (reg & I2SR_IIF)
 			break;
 
@@ -186,7 +198,7 @@ static int i2c_fsl_trx_complete(struct i2c_adapter *adapter)
 			return -EIO;
 		}
 	}
-	writeb(0, base + FSL_I2C_I2SR);
+	fsl_i2c_write_reg(0, i2c_fsl, FSL_I2C_I2SR);
 
 	return 0;
 }
@@ -194,12 +206,11 @@ static int i2c_fsl_trx_complete(struct i2c_adapter *adapter)
 static int i2c_fsl_acked(struct i2c_adapter *adapter)
 {
 	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
-	void __iomem *base = i2c_fsl->base;
 	uint64_t start;
 
 	start = get_time_ns();
 	while (1) {
-		unsigned int reg = readb(base + FSL_I2C_I2SR);
+		unsigned int reg = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2SR);
 		if (!(reg & I2SR_RXAK))
 			break;
 
@@ -215,25 +226,24 @@ static int i2c_fsl_acked(struct i2c_adapter *adapter)
 static int i2c_fsl_start(struct i2c_adapter *adapter)
 {
 	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
-	void __iomem *base = i2c_fsl->base;
 	unsigned int temp = 0;
 	int result;
 
-	writeb(i2c_fsl->ifdr, base + FSL_I2C_IFDR);
+	fsl_i2c_write_reg(i2c_fsl->ifdr, fsl_i2c, FSL_I2C_IFDR);
 	if (i2c_fsl->dfsrr != -1)
-		writeb(i2c_fsl->dfsrr, base + FSL_I2C_DFSRR);
+		fsl_i2c_write_reg(i2c_fsl->dfsrr, fsl_i2c, FSL_I2C_DFSRR);
 
 	/* Enable I2C controller */
-	writeb(0, base + FSL_I2C_I2SR);
-	writeb(I2CR_IEN, base + FSL_I2C_I2CR);
+	fsl_i2c_write_reg(0, fsl_i2c, FSL_I2C_I2SR);
+	fsl_i2c_write_reg(I2CR_IEN, fsl_i2c, FSL_I2C_I2CR);
 
 	/* Wait controller to be stable */
 	udelay(100);
 
 	/* Start I2C transaction */
-	temp = readb(base + FSL_I2C_I2CR);
+	temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2CR);
 	temp |= I2CR_MSTA;
-	writeb(temp, base + FSL_I2C_I2CR);
+	fsl_i2c_write_reg(temp, fsl_i2c, FSL_I2C_I2CR);
 
 	result = i2c_fsl_bus_busy(adapter, 1);
 	if (result) {
@@ -246,7 +256,7 @@ static int i2c_fsl_start(struct i2c_adapter *adapter)
 	i2c_fsl->stopped = 0;
 
 	temp |= I2CR_MTX | I2CR_TXAK;
-	writeb(temp, base + FSL_I2C_I2CR);
+	fsl_i2c_write_reg(temp, fsl_i2c, FSL_I2C_I2CR);
 
 	return result;
 }
@@ -254,14 +264,13 @@ static int i2c_fsl_start(struct i2c_adapter *adapter)
 static void i2c_fsl_stop(struct i2c_adapter *adapter)
 {
 	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
-	void __iomem *base = i2c_fsl->base;
 	unsigned int temp = 0;
 
 	if (!i2c_fsl->stopped) {
 		/* Stop I2C transaction */
-		temp = readb(base + FSL_I2C_I2CR);
+		temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2CR);
 		temp &= ~(I2CR_MSTA | I2CR_MTX);
-		writeb(temp, base + FSL_I2C_I2CR);
+		fsl_i2c_write_reg(temp, fsl_i2c, FSL_I2C_I2CR);
 		/* wait for the stop condition to be send, otherwise the i2c
 		 * controller is disabled before the STOP is sent completely */
 		i2c_fsl->stopped = i2c_fsl_bus_busy(adapter, 0) ? 0 : 1;
@@ -273,14 +282,13 @@ static void i2c_fsl_stop(struct i2c_adapter *adapter)
 	}
 
 	/* Disable I2C controller, and force our state to stopped */
-	writeb(0, base + FSL_I2C_I2CR);
+	fsl_i2c_write_reg(0, fsl_i2c, FSL_I2C_I2CR);
 }
 
 #ifdef CONFIG_PPC
 static void i2c_fsl_set_clk(struct fsl_i2c_struct *i2c_fsl,
 				    unsigned int rate)
 {
-	void __iomem *base;
 	unsigned int i2c_clk;
 	unsigned short divider;
 	/*
@@ -295,7 +303,6 @@ static void i2c_fsl_set_clk(struct fsl_i2c_struct *i2c_fsl,
 	unsigned long c_div, est_div;
 
 	fdr = 0x31; /* Default if no FDR found */
-	base = i2c_fsl->base;
 	i2c_clk = fsl_get_i2c_freq();
 	divider = min((unsigned short)(i2c_clk / rate), (unsigned short) -1);
 
@@ -387,7 +394,6 @@ static void i2c_fsl_set_clk(struct fsl_i2c_struct *i2c_fsl,
 static int i2c_fsl_write(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 {
 	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
-	void __iomem *base = i2c_fsl->base;
 	int i, result;
 
 	if ( !(msgs->flags & I2C_M_DATA_ONLY) ) {
@@ -396,7 +402,7 @@ static int i2c_fsl_write(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 			__func__, msgs->addr << 1);
 
 		/* write slave address */
-		writeb(msgs->addr << 1, base + FSL_I2C_I2DR);
+		fsl_i2c_write_reg(msgs->addr << 1, fsl_i2c, FSL_I2C_I2DR);
 
 		result = i2c_fsl_trx_complete(adapter);
 		if (result)
@@ -411,7 +417,7 @@ static int i2c_fsl_write(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 		dev_dbg(&adapter->dev,
 			"<%s> write byte: B%d=0x%02X\n",
 			__func__, i, msgs->buf[i]);
-		writeb(msgs->buf[i], base + FSL_I2C_I2DR);
+		fsl_i2c_write_reg(msgs->buf[i], fsl_i2c, FSL_I2C_I2DR);
 
 		result = i2c_fsl_trx_complete(adapter);
 		if (result)
@@ -426,12 +432,11 @@ static int i2c_fsl_write(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 static int i2c_fsl_read(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 {
 	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
-	void __iomem *base = i2c_fsl->base;
 	int i, result;
 	unsigned int temp;
 
 	/* clear IIF */
-	writeb(0x0, base + FSL_I2C_I2SR);
+	fsl_i2c_write_reg(0x0, fsl_i2c, FSL_I2C_I2SR);
 
 	if ( !(msgs->flags & I2C_M_DATA_ONLY) ) {
 		dev_dbg(&adapter->dev,
@@ -439,7 +444,7 @@ static int i2c_fsl_read(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 			__func__, (msgs->addr << 1) | 0x01);
 
 		/* write slave address */
-		writeb((msgs->addr << 1) | 0x01, base + FSL_I2C_I2DR);
+		fsl_i2c_write_reg((msgs->addr << 1) | 0x01, fsl_i2c, FSL_I2C_I2DR);
 
 		result = i2c_fsl_trx_complete(adapter);
 		if (result)
@@ -450,13 +455,13 @@ static int i2c_fsl_read(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 	}
 
 	/* setup bus to read data */
-	temp = readb(base + FSL_I2C_I2CR);
+	temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2CR);
 	temp &= ~I2CR_MTX;
 	if (msgs->len - 1)
 		temp &= ~I2CR_TXAK;
-	writeb(temp, base + FSL_I2C_I2CR);
+	fsl_i2c_write_reg(temp, fsl_i2c, FSL_I2C_I2CR);
 
-	readb(base + FSL_I2C_I2DR);	/* dummy read */
+	fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2DR);	/* dummy read */
 
 	/* read data */
 	for (i = 0; i < msgs->len; i++) {
@@ -469,9 +474,9 @@ static int i2c_fsl_read(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 			 * It must generate STOP before read I2DR to prevent
 			 * controller from generating another clock cycle
 			 */
-			temp = readb(base + FSL_I2C_I2CR);
+			temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2CR);
 			temp &= ~(I2CR_MSTA | I2CR_MTX);
-			writeb(temp, base + FSL_I2C_I2CR);
+			fsl_i2c_write_reg(temp, fsl_i2c, FSL_I2C_I2CR);
 
 			/*
 			 * adding this delay helps on low bitrates
@@ -481,11 +486,11 @@ static int i2c_fsl_read(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 			i2c_fsl_bus_busy(adapter, 0);
 			i2c_fsl->stopped = 1;
 		} else if (i == (msgs->len - 2)) {
-			temp = readb(base + FSL_I2C_I2CR);
+			temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2CR);
 			temp |= I2CR_TXAK;
-			writeb(temp, base + FSL_I2C_I2CR);
+			fsl_i2c_write_reg(temp, fsl_i2c, FSL_I2C_I2CR);
 		}
-		msgs->buf[i] = readb(base + FSL_I2C_I2DR);
+		msgs->buf[i] = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2DR);
 
 		dev_dbg(&adapter->dev, "<%s> read byte: B%d=0x%02X\n",
 			__func__, i, msgs->buf[i]);
@@ -497,7 +502,6 @@ static int i2c_fsl_xfer(struct i2c_adapter *adapter,
 			struct i2c_msg *msgs, int num)
 {
 	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
-	void __iomem *base = i2c_fsl->base;
 	unsigned int i, temp;
 	int result;
 
@@ -514,9 +518,9 @@ static int i2c_fsl_xfer(struct i2c_adapter *adapter,
 	/* read/write data */
 	for (i = 0; i < num; i++) {
 		if (i && !(msgs[i].flags & I2C_M_DATA_ONLY)) {
-			temp = readb(base + FSL_I2C_I2CR);
+			temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2CR);
 			temp |= I2CR_RSTA;
-			writeb(temp, base + FSL_I2C_I2CR);
+			fsl_i2c_write_reg(temp, fsl_i2c, FSL_I2C_I2CR);
 
 			result = i2c_fsl_bus_busy(adapter, 1);
 			if (result)
@@ -623,8 +627,8 @@ static int __init i2c_fsl_probe(struct device_d *pdev)
 		i2c_fsl_set_clk(i2c_fsl, FSL_I2C_BIT_RATE);
 
 	/* Set up chip registers to defaults */
-	writeb(0, i2c_fsl->base + FSL_I2C_I2CR);
-	writeb(0, i2c_fsl->base + FSL_I2C_I2SR);
+	fsl_i2c_write_reg(0, i2c_fsl, FSL_I2C_I2CR);
+	fsl_i2c_write_reg(0, i2c_fsl, FSL_I2C_I2SR);
 
 	/* Add I2C adapter */
 	ret = i2c_add_numbered_adapter(&i2c_fsl->adapter);
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 20/28] i.MX: esdhc: Do not rely on CPU type for quirks
From: Andrey Smirnov @ 2016-11-09 16:14 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

CPU type is not a reliable indicator of the underlying type of IP core
used, since there's no 1:1 mapping between the two. As example of one
such violation consider Vybrid SoC which contains IP block from i.MX53.

Instead port feature flags from corresponding Linux kernel driver and
use the ones that are relevant.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/mci/imx-esdhc.c | 121 +++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 100 insertions(+), 21 deletions(-)

diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c
index 262a904..764a106 100644
--- a/drivers/mci/imx-esdhc.c
+++ b/drivers/mci/imx-esdhc.c
@@ -35,28 +35,81 @@
 #include <mach/generic.h>
 #include <mach/esdhc.h>
 #include <gpio.h>
+#include <of_device.h>
 
 #include "sdhci.h"
 #include "imx-esdhc.h"
 
+/*
+ * The CMDTYPE of the CMD register (offset 0xE) should be set to
+ * "11" when the STOP CMD12 is issued on imx53 to abort one
+ * open ended multi-blk IO. Otherwise the TC INT wouldn't
+ * be generated.
+ * In exact block transfer, the controller doesn't complete the
+ * operations automatically as required at the end of the
+ * transfer and remains on hold if the abort command is not sent.
+ * As a result, the TC flag is not asserted and SW  received timeout
+ * exeception. Bit1 of Vendor Spec registor is used to fix it.
+ */
+#define ESDHC_FLAG_MULTIBLK_NO_INT	BIT(1)
+/*
+ * The flag enables the workaround for ESDHC errata ENGcm07207 which
+ * affects i.MX25 and i.MX35.
+ */
+#define ESDHC_FLAG_ENGCM07207		BIT(2)
+/*
+ * The flag tells that the ESDHC controller is an USDHC block that is
+ * integrated on the i.MX6 series.
+ */
+#define ESDHC_FLAG_USDHC		BIT(3)
+/* The IP supports manual tuning process */
+#define ESDHC_FLAG_MAN_TUNING		BIT(4)
+/* The IP supports standard tuning process */
+#define ESDHC_FLAG_STD_TUNING		BIT(5)
+/* The IP has SDHCI_CAPABILITIES_1 register */
+#define ESDHC_FLAG_HAVE_CAP1		BIT(6)
+/*
+ * The IP has errata ERR004536
+ * uSDHC: ADMA Length Mismatch Error occurs if the AHB read access is slow,
+ * when reading data from the card
+ */
+#define ESDHC_FLAG_ERR004536		BIT(7)
+/* The IP supports HS200 mode */
+#define ESDHC_FLAG_HS200		BIT(8)
+/* The IP supports HS400 mode */
+#define ESDHC_FLAG_HS400		BIT(9)
+
+
 #define IMX_SDHCI_WML		0x44
 #define IMX_SDHCI_MIXCTRL	0x48
 #define IMX_SDHCI_DLL_CTRL	0x60
 #define IMX_SDHCI_MIX_CTRL_FBCLK_SEL	(BIT(25))
 
+struct esdhc_soc_data {
+	u32 flags;
+};
+
 struct fsl_esdhc_host {
 	struct mci_host		mci;
 	void __iomem		*regs;
 	struct device_d		*dev;
 	struct clk		*clk;
+	const struct esdhc_soc_data *socdata;
 };
 
 #define to_fsl_esdhc(mci)	container_of(mci, struct fsl_esdhc_host, mci)
 
 #define  SDHCI_CMD_ABORTCMD (0xC0 << 16)
 
+static inline int esdhc_is_usdhc(struct fsl_esdhc_host *data)
+{
+	return !!(data->socdata->flags & ESDHC_FLAG_USDHC);
+}
+
+
 /* Return the XFERTYP flags for a given command and data packet */
-static u32 esdhc_xfertyp(struct mci_cmd *cmd, struct mci_data *data)
+static u32 esdhc_xfertyp(struct fsl_esdhc_host *host,
+			 struct mci_cmd *cmd, struct mci_data *data)
 {
 	u32 xfertyp = 0;
 
@@ -85,8 +138,8 @@ static u32 esdhc_xfertyp(struct mci_cmd *cmd, struct mci_data *data)
 		xfertyp |= COMMAND_RSPTYP_48_BUSY;
 	else if (cmd->resp_type & MMC_RSP_PRESENT)
 		xfertyp |= COMMAND_RSPTYP_48;
-	if ((cpu_is_mx50() || cpu_is_mx51() || cpu_is_mx53()) &&
-			cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
+	if ((host->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT) &&
+	    (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION))
 		xfertyp |= SDHCI_CMD_ABORTCMD;
 
 	return COMMAND_CMD(cmd->cmdidx) | xfertyp;
@@ -273,12 +326,12 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
 	}
 
 	/* Figure out the transfer arguments */
-	xfertyp = esdhc_xfertyp(cmd, data);
+	xfertyp = esdhc_xfertyp(host, cmd, data);
 
 	/* Send the command */
 	esdhc_write32(regs + SDHCI_ARGUMENT, cmd->cmdarg);
 
-	if (cpu_is_mx6()) {
+	if (esdhc_is_usdhc(host)) {
 		/* write lower-half of xfertyp to mixctrl */
 		mixctrl = xfertyp & 0xFFFF;
 		/* Keep the bits 22-25 of the register as is */
@@ -525,7 +578,7 @@ static int esdhc_reset(struct fsl_esdhc_host *host)
 			SYSCTL_RSTA);
 
 	/* extra register reset for i.MX6 Solo/DualLite */
-	if (cpu_is_mx6()) {
+	if (esdhc_is_usdhc(host)) {
 		/* reset bit FBCLK_SEL */
 		val = esdhc_read32(regs + IMX_SDHCI_MIXCTRL);
 		val &= ~IMX_SDHCI_MIX_CTRL_FBCLK_SEL;
@@ -570,6 +623,10 @@ static int fsl_esdhc_probe(struct device_d *dev)
 	host = xzalloc(sizeof(*host));
 	mci = &host->mci;
 
+	host->socdata = of_device_get_match_data(dev);
+	if (!host->socdata)
+		return -EINVAL;
+
 	host->clk = clk_get(dev, NULL);
 	if (IS_ERR(host->clk))
 		return PTR_ERR(host->clk);
@@ -634,22 +691,44 @@ static int fsl_esdhc_probe(struct device_d *dev)
 	return mci_register(&host->mci);
 }
 
+static struct esdhc_soc_data esdhc_imx25_data = {
+	.flags = ESDHC_FLAG_ENGCM07207,
+};
+
+static struct esdhc_soc_data esdhc_imx50_data = {
+	.flags = ESDHC_FLAG_MULTIBLK_NO_INT,
+	/* .flags = 0, */
+};
+
+static struct esdhc_soc_data esdhc_imx51_data = {
+	.flags = ESDHC_FLAG_MULTIBLK_NO_INT,
+	/* .flags = 0, */
+};
+
+static struct esdhc_soc_data esdhc_imx53_data = {
+	.flags = ESDHC_FLAG_MULTIBLK_NO_INT,
+};
+
+static struct esdhc_soc_data usdhc_imx6q_data = {
+	.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_MAN_TUNING,
+};
+
+static struct esdhc_soc_data usdhc_imx6sl_data = {
+	.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
+	       | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_ERR004536
+	       | ESDHC_FLAG_HS200,
+};
+
+
 static __maybe_unused struct of_device_id fsl_esdhc_compatible[] = {
-	{
-		.compatible = "fsl,imx25-esdhc",
-	}, {
-		.compatible = "fsl,imx50-esdhc",
-	}, {
-		.compatible = "fsl,imx51-esdhc",
-	}, {
-		.compatible = "fsl,imx53-esdhc",
-	}, {
-		.compatible = "fsl,imx6q-usdhc",
-	}, {
-		.compatible = "fsl,imx6sl-usdhc",
-	}, {
-		/* sentinel */
-	}
+
+	{ .compatible = "fsl,imx25-esdhc",  .data = &esdhc_imx25_data  },
+	{ .compatible = "fsl,imx50-esdhc",  .data = &esdhc_imx50_data  },
+	{ .compatible = "fsl,imx51-esdhc",  .data = &esdhc_imx51_data  },
+	{ .compatible = "fsl,imx53-esdhc",  .data = &esdhc_imx53_data  },
+	{ .compatible = "fsl,imx6q-usdhc",  .data = &usdhc_imx6q_data  },
+	{ .compatible = "fsl,imx6sl-usdhc", .data = &usdhc_imx6sl_data },
+	{ /* sentinel */ }
 };
 
 static struct driver_d fsl_esdhc_driver = {
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 17/28] i.MX: Add 'lpuart' serial driver
From: Andrey Smirnov @ 2016-11-09 16:14 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Add 'lpuart' serial driver, based on analogous driver from U-Boot

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/serial/Kconfig         |   5 +
 drivers/serial/Makefile        |   1 +
 drivers/serial/serial_lpuart.c | 217 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 223 insertions(+)
 create mode 100644 drivers/serial/serial_lpuart.c

diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index b112d7e..4eab437 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -137,4 +137,9 @@ config DRIVER_SERIAL_DIGIC
 	bool "Canon DIGIC serial driver"
 	depends on ARCH_DIGIC
 
+config DRIVER_SERIAL_LPUART
+	depends on ARCH_VF610
+	default y
+	bool "LPUART serial driver"
+
 endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 189e777..7d1bae1 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_DRIVER_SERIAL_AUART)		+= serial_auart.o
 obj-$(CONFIG_DRIVER_SERIAL_CADENCE)		+= serial_cadence.o
 obj-$(CONFIG_DRIVER_SERIAL_EFI_STDIO)		+= efi-stdio.o
 obj-$(CONFIG_DRIVER_SERIAL_DIGIC)		+= serial_digic.o
+obj-$(CONFIG_DRIVER_SERIAL_LPUART)		+= serial_lpuart.o
diff --git a/drivers/serial/serial_lpuart.c b/drivers/serial/serial_lpuart.c
new file mode 100644
index 0000000..52fb6d3
--- /dev/null
+++ b/drivers/serial/serial_lpuart.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2016 Zodiac Inflight Innovation
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
+ *
+ * Based on analogous driver from U-Boot
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <malloc.h>
+#include <notifier.h>
+#include <io.h>
+#include <of.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <serial/lpuart.h>
+
+struct lpuart {
+	struct console_device cdev;
+	int baudrate;
+	int dte_mode;
+	struct notifier_block notify;
+	struct resource *io;
+	void __iomem *base;
+	struct clk *clk;
+};
+
+static struct lpuart *cdev_to_lpuart(struct console_device *cdev)
+{
+	return container_of(cdev, struct lpuart, cdev);
+}
+
+static struct lpuart *nb_to_lpuart(struct notifier_block *nb)
+{
+	return container_of(nb, struct lpuart, notify);
+}
+
+static void lpuart_enable(struct lpuart *lpuart, bool on)
+{
+	u8 ctrl;
+
+	ctrl = readb(lpuart->base + UARTCR2);
+	if (on)
+		ctrl |= UARTCR2_TE | UARTCR2_RE;
+	else
+		ctrl &= ~(UARTCR2_TE | UARTCR2_RE);
+	writeb(ctrl, lpuart->base + UARTCR2);
+}
+
+static int lpuart_serial_setbaudrate(struct console_device *cdev,
+				     int baudrate)
+{
+	struct lpuart *lpuart = cdev_to_lpuart(cdev);
+
+	lpuart_enable(lpuart, false);
+
+	lpuart_setbrg(lpuart->base,
+		      clk_get_rate(lpuart->clk),
+		      baudrate);
+
+	lpuart_enable(lpuart, true);
+
+	lpuart->baudrate = baudrate;
+
+	return 0;
+}
+
+static int lpuart_serial_getc(struct console_device *cdev)
+{
+	bool ready;
+	struct lpuart *lpuart = cdev_to_lpuart(cdev);
+
+	do {
+		const u8 sr1 = readb(lpuart->base + UARTSR1);
+		ready = !!(sr1 & (UARTSR1_OR | UARTSR1_RDRF));
+	} while (!ready);
+
+	return readb(lpuart->base + UARTDR);
+}
+
+static void lpuart_serial_putc(struct console_device *cdev, char c)
+{
+	lpuart_putc(cdev_to_lpuart(cdev)->base, c);
+}
+
+/* Test whether a character is in the RX buffer */
+static int lpuart_serial_tstc(struct console_device *cdev)
+{
+	return !!readb(cdev_to_lpuart(cdev)->base + UARTRCFIFO);
+}
+
+static void lpuart_serial_flush(struct console_device *cdev)
+{
+	bool tx_empty;
+	struct lpuart *lpuart = cdev_to_lpuart(cdev);
+
+	do {
+		const u8 sr1 = readb(lpuart->base + UARTSR1);
+		tx_empty = !!(sr1 & UARTSR1_TDRE);
+	} while (!tx_empty);
+}
+
+static int lpuart_clocksource_clock_change(struct notifier_block *nb,
+					   unsigned long event, void *data)
+{
+	struct lpuart *lpuart = nb_to_lpuart(nb);
+
+	return lpuart_serial_setbaudrate(&lpuart->cdev, lpuart->baudrate);
+}
+
+static int lpuart_serial_probe(struct device_d *dev)
+{
+	int ret;
+	struct console_device *cdev;
+	struct lpuart *lpuart;
+	const char *devname;
+
+	lpuart    = xzalloc(sizeof(*lpuart));
+	cdev      = &lpuart->cdev;
+	dev->priv = lpuart;
+
+	lpuart->io = dev_request_mem_resource(dev, 0);
+	if (IS_ERR(lpuart->io)) {
+		ret = PTR_ERR(lpuart->io);
+		goto err_free;
+	}
+	lpuart->base = IOMEM(lpuart->io->start);
+
+	lpuart->clk = clk_get(dev, NULL);
+	if (IS_ERR(lpuart->clk)) {
+		ret = PTR_ERR(lpuart->clk);
+		dev_err(dev, "Failed to get UART clock %d\n", ret);
+		goto io_release;
+	}
+
+	ret = clk_enable(lpuart->clk);
+	if (ret) {
+		dev_err(dev, "Failed to enable UART clock %d\n", ret);
+		goto io_release;
+	}
+
+	cdev->dev    = dev;
+	cdev->tstc   = lpuart_serial_tstc;
+	cdev->putc   = lpuart_serial_putc;
+	cdev->getc   = lpuart_serial_getc;
+	cdev->flush  = lpuart_serial_flush;
+	cdev->setbrg = lpuart_serial_setbaudrate;
+
+	if (dev->device_node) {
+		devname = of_alias_get(dev->device_node);
+		if (devname) {
+			cdev->devname = xstrdup(devname);
+			cdev->devid   = DEVICE_ID_SINGLE;
+		}
+	}
+
+	cdev->linux_console_name = "ttyLP";
+
+	lpuart_setup_with_fifo(lpuart->base,
+			       clk_get_rate(lpuart->clk),
+			       15);
+
+	ret = console_register(cdev);
+	if (!ret) {
+		lpuart->notify.notifier_call = lpuart_clocksource_clock_change;
+		clock_register_client(&lpuart->notify);
+
+		return 0;
+	}
+
+	clk_put(lpuart->clk);
+io_release:
+	release_region(lpuart->io);
+err_free:
+	free(lpuart);
+
+	return ret;
+}
+
+static void lpuart_serial_remove(struct device_d *dev)
+{
+	struct lpuart *lpuart = dev->priv;
+
+	lpuart_serial_flush(&lpuart->cdev);
+	console_unregister(&lpuart->cdev);
+	release_region(lpuart->io);
+	clk_put(lpuart->clk);
+
+	free(lpuart);
+}
+
+static struct of_device_id lpuart_serial_dt_ids[] = {
+	{ .compatible = "fsl,vf610-lpuart" },
+	{}
+};
+
+static struct driver_d lpuart_serial_driver = {
+	.name   = "lpuart-serial",
+	.probe  = lpuart_serial_probe,
+	.remove = lpuart_serial_remove,
+	.of_compatible = DRV_OF_COMPAT(lpuart_serial_dt_ids),
+};
+console_platform_driver(lpuart_serial_driver);
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 16/28] vf610: Give enet_osc explicit "enet_ext" name
From: Andrey Smirnov @ 2016-11-09 16:14 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Give enet_osc explicit "enet_ext" name, since without it, Barebox
version of clk_set_parent fails when trying to re-parent "enet_sel".

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 arch/arm/dts/vf610-twr.dts | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/dts/vf610-twr.dts b/arch/arm/dts/vf610-twr.dts
index 54b4435..5947fdb 100644
--- a/arch/arm/dts/vf610-twr.dts
+++ b/arch/arm/dts/vf610-twr.dts
@@ -12,3 +12,7 @@
 &usbdev0 {
 	status = "disabled";
 };
+
+&enet_ext {
+	clock-output-names = "enet_ext";
+};
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 02/28] i.MX: Add register definitions for VF610 SoC
From: Andrey Smirnov @ 2016-11-09 16:13 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 arch/arm/mach-imx/include/mach/clock-vf610.h | 171 ++++++++++++++++++++
 arch/arm/mach-imx/include/mach/iomux-vf610.h | 226 +++++++++++++++++++++++++++
 arch/arm/mach-imx/include/mach/vf610-regs.h  | 110 +++++++++++++
 3 files changed, 507 insertions(+)
 create mode 100644 arch/arm/mach-imx/include/mach/clock-vf610.h
 create mode 100644 arch/arm/mach-imx/include/mach/iomux-vf610.h
 create mode 100644 arch/arm/mach-imx/include/mach/vf610-regs.h

diff --git a/arch/arm/mach-imx/include/mach/clock-vf610.h b/arch/arm/mach-imx/include/mach/clock-vf610.h
new file mode 100644
index 0000000..0fa70a4
--- /dev/null
+++ b/arch/arm/mach-imx/include/mach/clock-vf610.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2013-2014 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __MACH_CLOCK_VF610_H__
+#define __MACH_CLOCK_VF610_H__
+
+#define VF610_CCM_CCR				(VF610_CCM_BASE_ADDR + 0x00)
+#define VF610_CCM_CSR				(VF610_CCM_BASE_ADDR + 0x04)
+#define VF610_CCM_CCSR				(VF610_CCM_BASE_ADDR + 0x08)
+#define VF610_CCM_CACRR				(VF610_CCM_BASE_ADDR + 0x0c)
+#define VF610_CCM_CSCMR1			(VF610_CCM_BASE_ADDR + 0x10)
+#define VF610_CCM_CSCDR1			(VF610_CCM_BASE_ADDR + 0x14)
+#define VF610_CCM_CSCDR2			(VF610_CCM_BASE_ADDR + 0x18)
+#define VF610_CCM_CSCDR3			(VF610_CCM_BASE_ADDR + 0x1c)
+#define VF610_CCM_CSCMR2			(VF610_CCM_BASE_ADDR + 0x20)
+#define VF610_CCM_CTOR				(VF610_CCM_BASE_ADDR + 0x28)
+#define VF610_CCM_CLPCR				(VF610_CCM_BASE_ADDR + 0x80)
+#define VF610_CCM_CMEOR5			(VF610_CCM_BASE_ADDR + 0x84)
+#define VF610_CCM_CPPDSR			(VF610_CCM_BASE_ADDR + 0x88)
+#define VF610_CCM_CCOWR				(VF610_CCM_BASE_ADDR + 0x8c)
+#define VF610_CCM_CCPGR0			(VF610_CCM_BASE_ADDR + 0x90)
+#define VF610_CCM_CCPGR1			(VF610_CCM_BASE_ADDR + 0x94)
+#define VF610_CCM_CCPGR2			(VF610_CCM_BASE_ADDR + 0x98)
+#define VF610_CCM_CCPGR3			(VF610_CCM_BASE_ADDR + 0x9c)
+
+#define VF610_CCM_CCGRx_CGn(n)	((n) * 2)
+
+#define VF610_ANADIG_PLL1_CTRL			(VF610_ANADIG_BASE_ADDR + 0x270)
+#define VF610_ANADIG_PLL1_NUM			(VF610_ANADIG_BASE_ADDR + 0x290)
+#define VF610_ANADIG_PLL1_DENOM			(VF610_ANADIG_BASE_ADDR + 0x2A0)
+#define VF610_ANADIG_PLL2_CTRL			(VF610_ANADIG_BASE_ADDR + 0x30)
+#define VF610_ANADIG_PLL2_NUM			(VF610_ANADIG_BASE_ADDR + 0x50)
+#define VF610_ANADIG_PLL3_CTRL			(VF610_ANADIG_BASE_ADDR + 0x10)
+#define VF610_ANADIG_PLL4_CTRL			(VF610_ANADIG_BASE_ADDR + 0x70)
+#define VF610_ANADIG_PLL5_CTRL			(VF610_ANADIG_BASE_ADDR + 0xe0)
+#define VF610_ANADIG_PLL6_CTRL			(VF610_ANADIG_BASE_ADDR + 0xa0)
+#define VF610_ANADIG_PLL7_CTRL			(VF610_ANADIG_BASE_ADDR + 0x20)
+#define VF610_ANADIG_ANA_MISC1			(VF610_ANADIG_BASE_ADDR + 0x160)
+#define VF610_ANADIG_LOCK			(VF610_ANADIG_BASE_ADDR + 0x2C0)
+
+#define CCM_CCR_FIRC_EN				(1 << 16)
+#define CCM_CCR_OSCNT_MASK			0xff
+#define CCM_CCR_OSCNT(v)			((v) & 0xff)
+
+#define CCM_CCSR_PLL2_PFD_CLK_SEL_OFFSET	19
+#define CCM_CCSR_PLL2_PFD_CLK_SEL_MASK		(0x7 << 19)
+#define CCM_CCSR_PLL2_PFD_CLK_SEL(v)		(((v) & 0x7) << 19)
+
+#define CCM_CCSR_PLL1_PFD_CLK_SEL_OFFSET	16
+#define CCM_CCSR_PLL1_PFD_CLK_SEL_MASK		(0x7 << 16)
+#define CCM_CCSR_PLL1_PFD_CLK_SEL(v)		(((v) & 0x7) << 16)
+
+#define CCM_CCSR_PLL2_PFD4_EN			(1 << 15)
+#define CCM_CCSR_PLL2_PFD3_EN			(1 << 14)
+#define CCM_CCSR_PLL2_PFD2_EN			(1 << 13)
+#define CCM_CCSR_PLL2_PFD1_EN			(1 << 12)
+#define CCM_CCSR_PLL1_PFD4_EN			(1 << 11)
+#define CCM_CCSR_PLL1_PFD3_EN			(1 << 10)
+#define CCM_CCSR_PLL1_PFD2_EN			(1 << 9)
+#define CCM_CCSR_PLL1_PFD1_EN			(1 << 8)
+
+#define CCM_CCSR_DDRC_CLK_SEL(v)		((v) << 6)
+#define CCM_CCSR_FAST_CLK_SEL(v)		((v) << 5)
+
+#define CCM_CCSR_SYS_CLK_SEL_OFFSET		0
+#define CCM_CCSR_SYS_CLK_SEL_MASK		0x7
+#define CCM_CCSR_SYS_CLK_SEL(v)			((v) & 0x7)
+
+#define CCM_CACRR_IPG_CLK_DIV_OFFSET		11
+#define CCM_CACRR_IPG_CLK_DIV_MASK		(0x3 << 11)
+#define CCM_CACRR_IPG_CLK_DIV(v)		(((v) & 0x3) << 11)
+#define CCM_CACRR_BUS_CLK_DIV_OFFSET		3
+#define CCM_CACRR_BUS_CLK_DIV_MASK		(0x7 << 3)
+#define CCM_CACRR_BUS_CLK_DIV(v)		(((v) & 0x7) << 3)
+#define CCM_CACRR_ARM_CLK_DIV_OFFSET		0
+#define CCM_CACRR_ARM_CLK_DIV_MASK		0x7
+#define CCM_CACRR_ARM_CLK_DIV(v)		((v) & 0x7)
+
+#define CCM_CSCMR1_QSPI0_CLK_SEL_OFFSET		22
+#define CCM_CSCMR1_QSPI0_CLK_SEL_MASK		(0x3 << 22)
+#define CCM_CSCMR1_QSPI0_CLK_SEL(v)		(((v) & 0x3) << 22)
+#define CCM_CSCMR1_ESDHC1_CLK_SEL_OFFSET	18
+#define CCM_CSCMR1_ESDHC1_CLK_SEL_MASK		(0x3 << 18)
+#define CCM_CSCMR1_ESDHC1_CLK_SEL(v)		(((v) & 0x3) << 18)
+#define CCM_CSCMR1_NFC_CLK_SEL_OFFSET		12
+#define CCM_CSCMR1_NFC_CLK_SEL_MASK		(0x3 << 12)
+#define CCM_CSCMR1_NFC_CLK_SEL(v)		(((v) & 0x3) << 12)
+
+#define CCM_CSCDR1_RMII_CLK_EN			(1 << 24)
+
+#define CCM_CSCDR2_NFC_EN			(1 << 9)
+#define CCM_CSCDR2_NFC_FRAC_DIV_EN		(1 << 13)
+#define CCM_CSCDR2_NFC_CLK_INV			(1 << 14)
+#define CCM_CSCDR2_NFC_FRAC_DIV_OFFSET		4
+#define CCM_CSCDR2_NFC_FRAC_DIV_MASK		(0xf << 4)
+#define CCM_CSCDR2_NFC_FRAC_DIV(v)		(((v) & 0xf) << 4)
+
+#define CCM_CSCDR2_ESDHC1_EN			(1 << 29)
+#define CCM_CSCDR2_ESDHC1_CLK_DIV_OFFSET	20
+#define CCM_CSCDR2_ESDHC1_CLK_DIV_MASK		(0xf << 20)
+#define CCM_CSCDR2_ESDHC1_CLK_DIV(v)		(((v) & 0xf) << 20)
+
+#define CCM_CSCDR3_NFC_PRE_DIV_OFFSET		13
+#define CCM_CSCDR3_NFC_PRE_DIV_MASK		(0x7 << 13)
+#define CCM_CSCDR3_NFC_PRE_DIV(v)		(((v) & 0x7) << 13)
+#define CCM_CSCDR3_QSPI0_EN			(1 << 4)
+#define CCM_CSCDR3_QSPI0_DIV(v)			((v) << 3)
+#define CCM_CSCDR3_QSPI0_X2_DIV(v)		((v) << 2)
+#define CCM_CSCDR3_QSPI0_X4_DIV(v)		((v) & 0x3)
+
+#define CCM_CSCMR2_RMII_CLK_SEL_OFFSET		4
+#define CCM_CSCMR2_RMII_CLK_SEL_MASK		(0x3 << 4)
+#define CCM_CSCMR2_RMII_CLK_SEL(v)		(((v) & 0x3) << 4)
+
+#define CCM_REG_CTRL_MASK			0xffffffff
+#define CCM_CCGR0_UART0_CTRL_MASK               (0x3 << 14)
+#define CCM_CCGR0_UART1_CTRL_MASK		(0x3 << 16)
+#define CCM_CCGR0_DSPI0_CTRL_MASK		(0x3 << 24)
+#define CCM_CCGR0_DSPI1_CTRL_MASK		(0x3 << 26)
+#define CCM_CCGR1_USBC0_CTRL_MASK		(0x3 << 8)
+#define CCM_CCGR1_PIT_CTRL_MASK			(0x3 << 14)
+#define CCM_CCGR1_WDOGA5_CTRL_MASK		(0x3 << 28)
+#define CCM_CCGR2_QSPI0_CTRL_MASK		(0x3 << 8)
+#define CCM_CCGR2_IOMUXC_CTRL_MASK		(0x3 << 16)
+#define CCM_CCGR2_PORTA_CTRL_MASK		(0x3 << 18)
+#define CCM_CCGR2_PORTB_CTRL_MASK		(0x3 << 20)
+#define CCM_CCGR2_PORTC_CTRL_MASK		(0x3 << 22)
+#define CCM_CCGR2_PORTD_CTRL_MASK		(0x3 << 24)
+#define CCM_CCGR2_PORTE_CTRL_MASK		(0x3 << 26)
+#define CCM_CCGR3_ANADIG_CTRL_MASK		0x3
+#define CCM_CCGR3_SCSC_CTRL_MASK		(0x3 << 4)
+#define CCM_CCGR4_WKUP_CTRL_MASK		(0x3 << 20)
+#define CCM_CCGR4_CCM_CTRL_MASK			(0x3 << 22)
+#define CCM_CCGR4_GPC_CTRL_MASK			(0x3 << 24)
+#define CCM_CCGR4_I2C0_CTRL_MASK		(0x3 << 12)
+#define CCM_CCGR4_I2C1_CTRL_MASK		(0x3 << 14)
+#define CCM_CCGR6_OCOTP_CTRL_MASK		(0x3 << 10)
+#define CCM_CCGR6_DSPI2_CTRL_MASK		(0x3 << 24)
+#define CCM_CCGR6_DSPI3_CTRL_MASK		(0x3 << 26)
+#define CCM_CCGR6_DDRMC_CTRL_MASK		(0x3 << 28)
+#define CCM_CCGR7_SDHC1_CTRL_MASK		(0x3 << 4)
+#define CCM_CCGR7_USBC1_CTRL_MASK		(0x3 << 8)
+#define CCM_CCGR9_FEC0_CTRL_MASK		0x3
+#define CCM_CCGR9_FEC1_CTRL_MASK		(0x3 << 2)
+#define CCM_CCGR10_NFC_CTRL_MASK		0x3
+#define CCM_CCGR10_I2C2_CTRL_MASK		(0x3 << 12)
+#define CCM_CCGR10_I2C3_CTRL_MASK		(0x3 << 14)
+
+#define ANADIG_PLL7_CTRL_BYPASS			(1 << 16)
+#define ANADIG_PLL7_CTRL_ENABLE			(1 << 13)
+#define ANADIG_PLL7_CTRL_POWERDOWN		(1 << 12)
+#define ANADIG_PLL7_CTRL_DIV_SELECT		(1 << 1)
+#define ANADIG_PLL5_CTRL_BYPASS			(1 << 16)
+#define ANADIG_PLL5_CTRL_ENABLE			(1 << 13)
+#define ANADIG_PLL5_CTRL_POWERDOWN		(1 << 12)
+#define ANADIG_PLL5_CTRL_DIV_SELECT		1
+#define ANADIG_PLL3_CTRL_BYPASS			(1 << 16)
+#define ANADIG_PLL3_CTRL_ENABLE			(1 << 13)
+#define ANADIG_PLL3_CTRL_POWERDOWN		(1 << 12)
+#define ANADIG_PLL3_CTRL_DIV_SELECT		(1 << 1)
+#define ANADIG_PLL2_CTRL_ENABLE			(1 << 13)
+#define ANADIG_PLL2_CTRL_POWERDOWN		(1 << 12)
+#define ANADIG_PLL2_CTRL_DIV_SELECT		1
+#define ANADIG_PLL1_CTRL_ENABLE			(1 << 13)
+#define ANADIG_PLL1_CTRL_POWERDOWN		(1 << 12)
+#define ANADIG_PLL1_CTRL_DIV_SELECT		1
+
+#endif
diff --git a/arch/arm/mach-imx/include/mach/iomux-vf610.h b/arch/arm/mach-imx/include/mach/iomux-vf610.h
new file mode 100644
index 0000000..1535628
--- /dev/null
+++ b/arch/arm/mach-imx/include/mach/iomux-vf610.h
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2013-2014 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __MACH_IOMUX_VF610_H__
+#define __MACH_IOMUX_VF610_H__
+
+#include <mach/iomux-v3.h>
+
+#undef PAD_CTL_ODE
+#undef PAD_CTL_PKE
+#undef PAD_CTL_PUE
+
+enum {
+	PAD_MUX_MODE_SHIFT		= 20,
+	PAD_CTL_INPUT_DIFFERENTIAL	= 1 << 16,
+	PAD_CTL_SPEED_MED		= 1 << 12,
+	PAD_CTL_SPEED_HIGH		= 3 << 12,
+	PAD_CTL_SRE			= 1 << 11,
+	PAD_CTL_ODE			= 1 << 10,
+	PAD_CTL_DSE_150ohm		= 1 << 6,
+	PAD_CTL_DSE_50ohm		= 3 << 6,
+	PAD_CTL_DSE_25ohm		= 6 << 6,
+	PAD_CTL_DSE_20ohm		= 7 << 6,
+	PAD_CTL_PKE			= 1 << 3,
+	PAD_CTL_PUE			= 1 << 2 | PAD_CTL_PKE,
+	PAD_CTL_OBE_IBE_ENABLE		= 3 << 0,
+	PAD_CTL_OBE_ENABLE		= 1 << 1,
+	PAD_CTL_IBE_ENABLE		= 1 << 0,
+};
+
+/* These 2 defines are for pins that may not have a mux register, but could
+ * have a pad setting register, and vice-versa. */
+#define __NA_	0x00
+
+/* Pad control groupings */
+enum {
+
+	VF610_UART_PAD_CTRL	= PAD_CTL_PUS_100K_UP | PAD_CTL_DSE_25ohm | PAD_CTL_OBE_IBE_ENABLE,
+	VF610_SDHC_PAD_CTRL	= PAD_CTL_PUS_100K_UP | PAD_CTL_DSE_20ohm | PAD_CTL_OBE_IBE_ENABLE,
+	VF610_ENET_PAD_CTRL	= PAD_CTL_PUS_47K_UP | PAD_CTL_DSE_50ohm | PAD_CTL_OBE_IBE_ENABLE,
+	VF610_DDR_PAD_CTRL	= PAD_CTL_DSE_25ohm,
+	VF610_DDR_PAD_CTRL_1	= PAD_CTL_DSE_25ohm | PAD_CTL_INPUT_DIFFERENTIAL,
+	VF610_I2C_PAD_CTRL	= PAD_CTL_PUS_47K_UP | PAD_CTL_DSE_50ohm | PAD_CTL_SPEED_HIGH | PAD_CTL_ODE | PAD_CTL_OBE_IBE_ENABLE,
+	VF610_NFC_IO_PAD_CTRL	= PAD_CTL_SPEED_MED | PAD_CTL_SRE | PAD_CTL_DSE_50ohm | PAD_CTL_PUS_47K_UP | PAD_CTL_OBE_IBE_ENABLE,
+	VF610_NFC_CN_PAD_CTRL	= PAD_CTL_SPEED_MED | PAD_CTL_SRE | PAD_CTL_DSE_25ohm | PAD_CTL_OBE_ENABLE,
+	VF610_NFC_RB_PAD_CTRL	= PAD_CTL_SPEED_MED | PAD_CTL_SRE | PAD_CTL_PUS_22K_UP | PAD_CTL_IBE_ENABLE,
+	VF610_QSPI_PAD_CTRL	= PAD_CTL_SPEED_HIGH | PAD_CTL_DSE_150ohm | PAD_CTL_PUS_22K_UP | PAD_CTL_OBE_IBE_ENABLE,
+	VF610_GPIO_PAD_CTRL	= PAD_CTL_SPEED_MED | PAD_CTL_DSE_50ohm | PAD_CTL_IBE_ENABLE,
+	VF610_DSPI_PAD_CTRL	= PAD_CTL_OBE_ENABLE | PAD_CTL_DSE_20ohm | PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_HIGH,
+	VF610_DSPI_SIN_PAD_CTRL	= PAD_CTL_IBE_ENABLE | PAD_CTL_DSE_20ohm | PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_HIGH,
+};
+
+enum {
+	VF610_PAD_PTA6__RMII0_CLKIN	= IOMUX_PAD(0x0000, 0x0000, 2, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTA6__RMII0_CLKOUT	= IOMUX_PAD(0x0000, 0x0000, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTA7__GPIO_134	= IOMUX_PAD(0x0218, 0x0218, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTA17__GPIO_7		= IOMUX_PAD(0x001c, 0x001c, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTA20__GPIO_10	= IOMUX_PAD(0x0028, 0x0028, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTA21__GPIO_11	= IOMUX_PAD(0x002c, 0x002c, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTA30__GPIO_20	= IOMUX_PAD(0x0050, 0x0050, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTA31__GPIO_21	= IOMUX_PAD(0x0054, 0x0054, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB0__GPIO_22		= IOMUX_PAD(0x0058, 0x0058, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB1__GPIO_23		= IOMUX_PAD(0x005C, 0x005C, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB4__UART1_TX	= IOMUX_PAD(0x0068, 0x0068, 2, 0x0380, 0, VF610_UART_PAD_CTRL),
+	VF610_PAD_PTB5__UART1_RX	= IOMUX_PAD(0x006c, 0x006c, 2, 0x037c, 0, VF610_UART_PAD_CTRL),
+	VF610_PAD_PTB6__GPIO_28		= IOMUX_PAD(0x0070, 0x0070, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB7__GPIO_29		= IOMUX_PAD(0x0074, 0x0074, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB8__GPIO_30		= IOMUX_PAD(0x0078, 0x0078, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB9__GPIO_31		= IOMUX_PAD(0x007C, 0x007C, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB10__UART0_TX	= IOMUX_PAD(0x0080, 0x0080, 1, __NA_, 0, VF610_UART_PAD_CTRL),
+	VF610_PAD_PTB11__UART0_RX	= IOMUX_PAD(0x0084, 0x0084, 1, __NA_, 0, VF610_UART_PAD_CTRL),
+	VF610_PAD_PTB12__GPIO_34	= IOMUX_PAD(0x0088, 0x0088, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB13__GPIO_35	= IOMUX_PAD(0x008c, 0x008c, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB16__GPIO_38	= IOMUX_PAD(0x0098, 0x0098, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB17__GPIO_39	= IOMUX_PAD(0x009c, 0x009c, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB18__GPIO_40	= IOMUX_PAD(0x00a0, 0x00a0, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB21__GPIO_43	= IOMUX_PAD(0x00ac, 0x00ac, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB22__GPIO_44	= IOMUX_PAD(0x00b0, 0x00b0, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB23__GPIO_93	= IOMUX_PAD(0x0174, 0x0174, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB26__GPIO_96	= IOMUX_PAD(0x0180, 0x0180, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB28__GPIO_98	= IOMUX_PAD(0x0188, 0x0188, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTC1__GPIO_46		= IOMUX_PAD(0x00b8, 0x00b8, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTC1__RMII0_MDIO	= IOMUX_PAD(0x00b8, 0x00b8, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC0__GPIO_45		= IOMUX_PAD(0x00b4, 0x00b4, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTC0__RMII0_MDC	= IOMUX_PAD(0x00b4, 0x00b4, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC2__RMII0_CRS_DV	= IOMUX_PAD(0x00bc, 0x00bc, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC2__GPIO_47		= IOMUX_PAD(0x00bc, 0x00bc, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTC3__RMII0_RD1	= IOMUX_PAD(0x00c0, 0x00c0, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC3__GPIO_48		= IOMUX_PAD(0x00c0, 0x00c0, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTC4__RMII0_RD0	= IOMUX_PAD(0x00c4, 0x00c4, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC4__GPIO_49		= IOMUX_PAD(0x00c4, 0x00c4, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTC5__RMII0_RXER	= IOMUX_PAD(0x00c8, 0x00c8, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC5__GPIO_50		= IOMUX_PAD(0x00c8, 0x00c8, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTC6__RMII0_TD1	= IOMUX_PAD(0x00cc, 0x00cc, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC6__GPIO_51		= IOMUX_PAD(0x00cc, 0x00cc, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTC7__RMII0_TD0	= IOMUX_PAD(0x00D0, 0x00D0, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC7__GPIO_52		= IOMUX_PAD(0x00D0, 0x00D0, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTC8__RMII0_TXEN	= IOMUX_PAD(0x00D4, 0x00D4, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC8__GPIO_53		= IOMUX_PAD(0x00D4, 0x00D4, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTC10__RMII1_MDIO	= IOMUX_PAD(0x00dc, 0x00dc, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC9__RMII1_MDC	= IOMUX_PAD(0x00d8, 0x00d8, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC11__RMII1_CRS_DV	= IOMUX_PAD(0x00e0, 0x00e0, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC12__RMII1_RD1	= IOMUX_PAD(0x00e4, 0x00e4, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC13__RMII1_RD0	= IOMUX_PAD(0x00e8, 0x00e8, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC14__RMII1_RXER	= IOMUX_PAD(0x00ec, 0x00ec, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC15__RMII1_TD1	= IOMUX_PAD(0x00f0, 0x00f0, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC16__RMII1_TD0	= IOMUX_PAD(0x00f4, 0x00f4, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC17__RMII1_TXEN	= IOMUX_PAD(0x00f8, 0x00f8, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTD5__DSPI1_CS0	= IOMUX_PAD(0x0150, 0x0150, 3, 0x300, 1, VF610_DSPI_PAD_CTRL),
+	VF610_PAD_PTD6__DSPI1_SIN	= IOMUX_PAD(0x0154, 0x0154, 3, 0x2fc, 1, VF610_DSPI_SIN_PAD_CTRL),
+	VF610_PAD_PTD7__DSPI1_SOUT	= IOMUX_PAD(0x0158, 0x0158, 3, __NA_, 0, VF610_DSPI_PAD_CTRL),
+	VF610_PAD_PTD8__DSPI1_SCK	= IOMUX_PAD(0x015c, 0x015c, 3, 0x2f8, 1, VF610_DSPI_PAD_CTRL),
+	VF610_PAD_PTC29__GPIO_102	= IOMUX_PAD(0x0198, 0x0198, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTC30__GPIO_103	= IOMUX_PAD(0x019c, 0x019c, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTA24__ESDHC1_CLK	= IOMUX_PAD(0x0038, 0x0038, 5, __NA_, 0, VF610_SDHC_PAD_CTRL),
+	VF610_PAD_PTA25__ESDHC1_CMD	= IOMUX_PAD(0x003c, 0x003c, 5, __NA_, 0, VF610_SDHC_PAD_CTRL),
+	VF610_PAD_PTA26__ESDHC1_DAT0	= IOMUX_PAD(0x0040, 0x0040, 5, __NA_, 0, VF610_SDHC_PAD_CTRL),
+	VF610_PAD_PTA27__ESDHC1_DAT1	= IOMUX_PAD(0x0044, 0x0044, 5, __NA_, 0, VF610_SDHC_PAD_CTRL),
+	VF610_PAD_PTA28__ESDHC1_DAT2	= IOMUX_PAD(0x0048, 0x0048, 5, __NA_, 0, VF610_SDHC_PAD_CTRL),
+	VF610_PAD_PTA29__ESDHC1_DAT3	= IOMUX_PAD(0x004c, 0x004c, 5, __NA_, 0, VF610_SDHC_PAD_CTRL),
+	VF610_PAD_PTB14__I2C0_SCL	= IOMUX_PAD(0x0090, 0x0090, 2, 0x033c, 1, VF610_I2C_PAD_CTRL),
+	VF610_PAD_PTB15__I2C0_SDA	= IOMUX_PAD(0x0094, 0x0094, 2, 0x0340, 1, VF610_I2C_PAD_CTRL),
+	VF610_PAD_PTA22__I2C2_SCL	= IOMUX_PAD(0x0030, 0x0030, 6, 0x034c, 0, VF610_I2C_PAD_CTRL),
+	VF610_PAD_PTA23__I2C2_SDA	= IOMUX_PAD(0x0034, 0x0034, 6, 0x0350, 0, VF610_I2C_PAD_CTRL),
+	VF610_PAD_PTD31__NF_IO15	= IOMUX_PAD(0x00fc, 0x00fc, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD31__GPIO_63	= IOMUX_PAD(0x00fc, 0x00fc, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD30__NF_IO14	= IOMUX_PAD(0x0100, 0x0100, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD30__GPIO_64	= IOMUX_PAD(0x0100, 0x0100, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD29__NF_IO13	= IOMUX_PAD(0x0104, 0x0104, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD29__GPIO_65	= IOMUX_PAD(0x0104, 0x0104, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD28__NF_IO12	= IOMUX_PAD(0x0108, 0x0108, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD28__GPIO_66	= IOMUX_PAD(0x0108, 0x0108, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD27__NF_IO11	= IOMUX_PAD(0x010c, 0x010c, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD27__GPIO_67	= IOMUX_PAD(0x010c, 0x010c, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD26__NF_IO10	= IOMUX_PAD(0x0110, 0x0110, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD26__GPIO_68	= IOMUX_PAD(0x0110, 0x0110, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD25__NF_IO9		= IOMUX_PAD(0x0114, 0x0114, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD25__GPIO_69	= IOMUX_PAD(0x0114, 0x0114, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD24__NF_IO8		= IOMUX_PAD(0x0118, 0x0118, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD24__GPIO_70	= IOMUX_PAD(0x0118, 0x0118, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD23__NF_IO7		= IOMUX_PAD(0x011c, 0x011c, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD0__QSPI0_A_QSCK	= IOMUX_PAD(0x013c, 0x013c, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD1__QSPI0_A_CS0	= IOMUX_PAD(0x0140, 0x0140, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD2__QSPI0_A_DATA3	= IOMUX_PAD(0x0144, 0x0144, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD3__QSPI0_A_DATA2	= IOMUX_PAD(0x0148, 0x0148, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD4__GPIO_83		= IOMUX_PAD(0x014C, 0x014C, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD4__QSPI0_A_DATA1	= IOMUX_PAD(0x014c, 0x014c, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD5__QSPI0_A_DATA0	= IOMUX_PAD(0x0150, 0x0150, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD7__QSPI0_B_QSCK	= IOMUX_PAD(0x0158, 0x0158, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD8__QSPI0_B_CS0	= IOMUX_PAD(0x015c, 0x015c, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD9__QSPI0_B_DATA3	= IOMUX_PAD(0x0160, 0x0160, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD9__GPIO_88		= IOMUX_PAD(0x0160, 0x0160, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD10__QSPI0_B_DATA2	= IOMUX_PAD(0x0164, 0x0164, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD10__GPIO_89	= IOMUX_PAD(0x0164, 0x0164, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD11__QSPI0_B_DATA1	= IOMUX_PAD(0x0168, 0x0168, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD11__GPIO_90	= IOMUX_PAD(0x0168, 0x0168, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD12__QSPI0_B_DATA0	= IOMUX_PAD(0x016c, 0x016c, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD12__GPIO_91	= IOMUX_PAD(0x016c, 0x016c, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD13__GPIO_92	= IOMUX_PAD(0x0170, 0x0170, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD22__NF_IO6		= IOMUX_PAD(0x0120, 0x0120, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD21__NF_IO5		= IOMUX_PAD(0x0124, 0x0124, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD20__NF_IO4		= IOMUX_PAD(0x0128, 0x0128, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD19__NF_IO3		= IOMUX_PAD(0x012c, 0x012c, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD18__NF_IO2		= IOMUX_PAD(0x0130, 0x0130, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD17__NF_IO1		= IOMUX_PAD(0x0134, 0x0134, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD16__NF_IO0		= IOMUX_PAD(0x0138, 0x0138, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTB24__NF_WE_B	= IOMUX_PAD(0x0178, 0x0178, 5, __NA_, 0, VF610_NFC_CN_PAD_CTRL),
+	VF610_PAD_PTB25__NF_CE0_B	= IOMUX_PAD(0x017c, 0x017c, 5, __NA_, 0, VF610_NFC_CN_PAD_CTRL),
+	VF610_PAD_PTB27__NF_RE_B 	= IOMUX_PAD(0x0184, 0x0184, 6, __NA_, 0, VF610_NFC_CN_PAD_CTRL),
+	VF610_PAD_PTC26__NF_RB_B 	= IOMUX_PAD(0x018C, 0x018C, 5, __NA_, 0, VF610_NFC_RB_PAD_CTRL),
+	VF610_PAD_PTC27__NF_ALE  	= IOMUX_PAD(0x0190, 0x0190, 6, __NA_, 0, VF610_NFC_CN_PAD_CTRL),
+	VF610_PAD_PTC28__NF_CLE  	= IOMUX_PAD(0x0194, 0x0194, 6, __NA_, 0, VF610_NFC_CN_PAD_CTRL),
+	VF610_PAD_DDR_RESETB		= IOMUX_PAD(0x021c, 0x021c, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A15__DDR_A_15	= IOMUX_PAD(0x0220, 0x0220, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A14__DDR_A_14	= IOMUX_PAD(0x0224, 0x0224, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A13__DDR_A_13	= IOMUX_PAD(0x0228, 0x0228, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A12__DDR_A_12	= IOMUX_PAD(0x022c, 0x022c, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A11__DDR_A_11	= IOMUX_PAD(0x0230, 0x0230, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A10__DDR_A_10	= IOMUX_PAD(0x0234, 0x0234, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A9__DDR_A_9	= IOMUX_PAD(0x0238, 0x0238, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A8__DDR_A_8	= IOMUX_PAD(0x023c, 0x023c, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A7__DDR_A_7	= IOMUX_PAD(0x0240, 0x0240, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A6__DDR_A_6	= IOMUX_PAD(0x0244, 0x0244, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A5__DDR_A_5	= IOMUX_PAD(0x0248, 0x0248, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A4__DDR_A_4	= IOMUX_PAD(0x024c, 0x024c, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A3__DDR_A_3	= IOMUX_PAD(0x0250, 0x0250, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A2__DDR_A_2	= IOMUX_PAD(0x0254, 0x0254, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A1__DDR_A_1	= IOMUX_PAD(0x0258, 0x0258, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A0__DDR_A_0	= IOMUX_PAD(0x025c, 0x025c, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_BA2__DDR_BA_2	= IOMUX_PAD(0x0260, 0x0260, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_BA1__DDR_BA_1	= IOMUX_PAD(0x0264, 0x0264, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_BA0__DDR_BA_0	= IOMUX_PAD(0x0268, 0x0268, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_CAS__DDR_CAS_B	= IOMUX_PAD(0x026c, 0x026c, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_CKE__DDR_CKE_0	= IOMUX_PAD(0x0270, 0x0270, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_CLK__DDR_CLK_0	= IOMUX_PAD(0x0274, 0x0274, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_CS__DDR_CS_B_0	= IOMUX_PAD(0x0278, 0x0278, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_D15__DDR_D_15	= IOMUX_PAD(0x027c, 0x027c, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D14__DDR_D_14	= IOMUX_PAD(0x0280, 0x0280, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D13__DDR_D_13	= IOMUX_PAD(0x0284, 0x0284, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D12__DDR_D_12	= IOMUX_PAD(0x0288, 0x0288, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D11__DDR_D_11	= IOMUX_PAD(0x028c, 0x028c, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D10__DDR_D_10	= IOMUX_PAD(0x0290, 0x0290, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D9__DDR_D_9	= IOMUX_PAD(0x0294, 0x0294, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D8__DDR_D_8	= IOMUX_PAD(0x0298, 0x0298, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D7__DDR_D_7	= IOMUX_PAD(0x029c, 0x029c, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D6__DDR_D_6	= IOMUX_PAD(0x02a0, 0x02a0, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D5__DDR_D_5	= IOMUX_PAD(0x02a4, 0x02a4, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D4__DDR_D_4	= IOMUX_PAD(0x02a8, 0x02a8, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D3__DDR_D_3	= IOMUX_PAD(0x02ac, 0x02ac, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D2__DDR_D_2	= IOMUX_PAD(0x02b0, 0x02b0, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D1__DDR_D_1	= IOMUX_PAD(0x02b4, 0x02b4, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D0__DDR_D_0	= IOMUX_PAD(0x02b8, 0x02b8, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_DQM1__DDR_DQM_1	= IOMUX_PAD(0x02bc, 0x02bc, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_DQM0__DDR_DQM_0	= IOMUX_PAD(0x02c0, 0x02c0, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_DQS1__DDR_DQS_1	= IOMUX_PAD(0x02c4, 0x02c4, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_DQS0__DDR_DQS_0	= IOMUX_PAD(0x02c8, 0x02c8, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_RAS__DDR_RAS_B	= IOMUX_PAD(0x02cc, 0x02cc, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_WE__DDR_WE_B	= IOMUX_PAD(0x02d0, 0x02d0, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_ODT1__DDR_ODT_0	= IOMUX_PAD(0x02d4, 0x02d4, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_ODT0__DDR_ODT_1	= IOMUX_PAD(0x02d8, 0x02d8, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+};
+
+#endif	/* __IOMUX_VF610_H__ */
diff --git a/arch/arm/mach-imx/include/mach/vf610-regs.h b/arch/arm/mach-imx/include/mach/vf610-regs.h
new file mode 100644
index 0000000..8be220b
--- /dev/null
+++ b/arch/arm/mach-imx/include/mach/vf610-regs.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2013-2014 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __MACH_VF610_REGS_H__
+#define __MACH_VF610_REGS_H__
+
+#define VF610_IRAM_BASE_ADDR		0x3F000000	/* internal ram */
+#define VF610_IRAM_SIZE			0x00080000	/* 512 KB */
+
+#define VF610_AIPS0_BASE_ADDR		0x40000000
+#define VF610_AIPS1_BASE_ADDR		0x40080000
+
+/* AIPS 0 */
+#define VF610_MSCM_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00001000)
+#define VF610_MSCM_IR_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00001800)
+#define VF610_CA5SCU_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00002000)
+#define VF610_CA5_INTD_BASE_ADDR	(VF610_AIPS0_BASE_ADDR + 0x00003000)
+#define VF610_CA5_L2C_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00006000)
+#define VF610_NIC0_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00008000)
+#define VF610_NIC1_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00009000)
+#define VF610_NIC2_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x0000A000)
+#define VF610_NIC3_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x0000B000)
+#define VF610_NIC4_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x0000C000)
+#define VF610_NIC5_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x0000D000)
+#define VF610_NIC6_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x0000E000)
+#define VF610_NIC7_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x0000F000)
+#define VF610_AHBTZASC_BASE_ADDR	(VF610_AIPS0_BASE_ADDR + 0x00010000)
+#define VF610_TZASC_SYS0_BASE_ADDR	(VF610_AIPS0_BASE_ADDR + 0x00011000)
+#define VF610_TZASC_SYS1_BASE_ADDR	(VF610_AIPS0_BASE_ADDR + 0x00012000)
+#define VF610_TZASC_GFX_BASE_ADDR	(VF610_AIPS0_BASE_ADDR + 0x00013000)
+#define VF610_TZASC_DDR0_BASE_ADDR	(VF610_AIPS0_BASE_ADDR + 0x00014000)
+#define VF610_TZASC_DDR1_BASE_ADDR	(VF610_AIPS0_BASE_ADDR + 0x00015000)
+#define VF610_CSU_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00017000)
+#define VF610_DMA0_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00018000)
+#define VF610_DMA0_TCD_BASE_ADDR	(VF610_AIPS0_BASE_ADDR + 0x00019000)
+#define VF610_SEMA4_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x0001D000)
+#define VF610_FB_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x0001E000)
+#define VF610_DMA_MUX0_BASE_ADDR	(VF610_AIPS0_BASE_ADDR + 0x00024000)
+#define VF610_UART1_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00027000)
+#define VF610_UART2_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00028000)
+#define VF610_UART3_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00029000)
+#define VF610_UART4_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x0002A000)
+#define VF610_SPI0_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x0002C000)
+#define VF610_SPI1_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x0002D000)
+#define VF610_SAI0_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x0002F000)
+#define VF610_SAI1_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00030000)
+#define VF610_SAI2_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00031000)
+#define VF610_SAI3_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00032000)
+#define VF610_CRC_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00033000)
+#define VF610_USBC0_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00034000)
+#define VF610_PDB_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00036000)
+#define VF610_PIT_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00037000)
+#define VF610_FTM0_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00038000)
+#define VF610_FTM1_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00039000)
+#define VF610_ADC_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x0003B000)
+#define VF610_TCON0_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x0003D000)
+#define VF610_WDOG1_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x0003E000)
+#define VF610_LPTMR_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00040000)
+#define VF610_RLE_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00042000)
+#define VF610_MLB_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00043000)
+#define VF610_QSPI0_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00044000)
+#define VF610_IOMUXC_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00048000)
+#define VF610_ANADIG_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00050000)
+#define VF610_USB_PHY0_BASE_ADDR	(VF610_AIPS0_BASE_ADDR + 0x00050800)
+#define VF610_USB_PHY1_BASE_ADDR	(VF610_AIPS0_BASE_ADDR + 0x00050C00)
+#define VF610_SCSC_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00052000)
+#define VF610_ASRC_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00060000)
+#define VF610_SPDIF_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00061000)
+#define VF610_ESAI_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00062000)
+#define VF610_ESAI_FIFO_BASE_ADDR	(VF610_AIPS0_BASE_ADDR + 0x00063000)
+#define VF610_WDOG_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00065000)
+#define VF610_I2C1_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00066000)
+#define VF610_I2C2_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00067000)
+#define VF610_I2C3_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x000E6000)
+#define VF610_I2C4_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x000E7000)
+#define VF610_WKUP_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x0006A000)
+#define VF610_CCM_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x0006B000)
+#define VF610_GPC_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x0006C000)
+#define VF610_VREG_DIG_BASE_ADDR	(VF610_AIPS0_BASE_ADDR + 0x0006D000)
+#define VF610_SRC_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x0006E000)
+#define VF610_CMU_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x0006F000)
+#define VF610_GPIO0_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x000FF000)
+#define VF610_GPIO1_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x000FF040)
+#define VF610_GPIO2_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x000FF080)
+#define VF610_GPIO3_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x000FF0C0)
+#define VF610_GPIO4_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x000FF100)
+
+/* AIPS 1 */
+#define VF610_OCOTP_BASE_ADDR		(VF610_AIPS1_BASE_ADDR + 0x00025000)
+#define VF610_DDR_BASE_ADDR		(VF610_AIPS1_BASE_ADDR + 0x0002E000)
+#define VF610_ESDHC0_BASE_ADDR		(VF610_AIPS1_BASE_ADDR + 0x00031000)
+#define VF610_ESDHC1_BASE_ADDR		(VF610_AIPS1_BASE_ADDR + 0x00032000)
+#define VF610_USBC1_BASE_ADDR		(VF610_AIPS1_BASE_ADDR + 0x00034000)
+#define VF610_ENET_BASE_ADDR		(VF610_AIPS1_BASE_ADDR + 0x00050000)
+#define VF610_ENET1_BASE_ADDR		(VF610_AIPS1_BASE_ADDR + 0x00051000)
+#define VF610_NFC_BASE_ADDR		(VF610_AIPS1_BASE_ADDR + 0x00060000)
+
+#define VF610_QSPI0_AMBA_BASE		0x20000000
+
+
+/* MSCM interrupt rounter */
+#define VF610_MSCM_IRSPRC(n)		(0x880 + 2 * (n))
+#define VF610_MSCM_CPxTYPE		0
+#define VF610_MSCM_IRSPRC_CP0_EN	1
+#define VF610_MSCM_IRSPRC_NUM		112
+
+#endif
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 13/28] i.MX: clk: Port imx_check_clocks()
From: Andrey Smirnov @ 2016-11-09 16:14 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Port imx_check_clocks() from Linux kernel.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/clk/imx/Makefile |  3 ++-
 drivers/clk/imx/clk.c    | 21 +++++++++++++++++++++
 drivers/clk/imx/clk.h    |  3 +++
 3 files changed, 26 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/imx/clk.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 893a1a5..06af530 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -4,7 +4,8 @@ obj-$(CONFIG_COMMON_CLK) +=	\
 	clk-pllv3.o		\
 	clk-pfd.o		\
 	clk-gate2.o		\
-	clk-gate-exclusive.o
+	clk-gate-exclusive.o	\
+	clk.o
 
 obj-$(CONFIG_ARCH_IMX1)   += clk-imx1.o
 obj-$(CONFIG_ARCH_IMX25)  += clk-imx25.o
diff --git a/drivers/clk/imx/clk.c b/drivers/clk/imx/clk.c
new file mode 100644
index 0000000..7488dfc
--- /dev/null
+++ b/drivers/clk/imx/clk.c
@@ -0,0 +1,21 @@
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <linux/clk.h>
+#include <io.h>
+#include <of.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+
+#include "clk.h"
+
+void __init imx_check_clocks(struct clk *clks[], unsigned int count)
+{
+	unsigned i;
+
+	for (i = 0; i < count; i++)
+		if (IS_ERR(clks[i]))
+			pr_err("i.MX clk %u: register failed with %ld\n",
+			       i, PTR_ERR(clks[i]));
+}
+
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index 35e480f..fd43fc2 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -109,4 +109,7 @@ static inline struct clk *imx_clk_busy_mux(const char *name, void __iomem *reg,
 struct clk *imx_clk_gate_exclusive(const char *name, const char *parent,
 		void __iomem *reg, u8 shift, u32 exclusive_mask);
 
+void imx_check_clocks(struct clk *clks[], unsigned int count);
+
+
 #endif /* __IMX_CLK_H */
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 12/28] i.MX: clk: Add IMX_PLLV3_USB_VF610 support
From: Andrey Smirnov @ 2016-11-09 16:14 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Add IMX_PLLV3_USB_VF610 PLLv3 types support clk-pllv3.c

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/clk/imx/clk-pllv3.c | 9 ++++++---
 drivers/clk/imx/clk.h       | 1 +
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c
index e38dcdf..29c0f1c 100644
--- a/drivers/clk/imx/clk-pllv3.c
+++ b/drivers/clk/imx/clk-pllv3.c
@@ -36,6 +36,7 @@ struct clk_pllv3 {
 	void __iomem	*base;
 	bool		powerup_set;
 	u32		div_mask;
+	u32		div_shift;
 	const char	*parent;
 };
 
@@ -92,7 +93,7 @@ static unsigned long clk_pllv3_recalc_rate(struct clk *clk,
 					   unsigned long parent_rate)
 {
 	struct clk_pllv3 *pll = to_clk_pllv3(clk);
-	u32 div = readl(pll->base)  & pll->div_mask;
+	u32 div = (readl(pll->base) >> pll->div_shift) & pll->div_mask;
 
 	return (div == 1) ? parent_rate * 22 : parent_rate * 20;
 }
@@ -120,8 +121,8 @@ static int clk_pllv3_set_rate(struct clk *clk, unsigned long rate,
 		return -EINVAL;
 
 	val = readl(pll->base);
-	val &= ~pll->div_mask;
-	val |= div;
+	val &= ~(pll->div_mask << pll->div_shift);
+	val |= div << pll->div_shift;
 	writel(val, pll->base);
 
 	return 0;
@@ -292,6 +293,8 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
 	case IMX_PLLV3_SYS:
 		ops = &clk_pllv3_sys_ops;
 		break;
+	case IMX_PLLV3_USB_VF610:
+		pll->div_shift = 1;
 	case IMX_PLLV3_USB:
 		ops = &clk_pllv3_ops;
 		pll->powerup_set = true;
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index 2aeb356..35e480f 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -71,6 +71,7 @@ enum imx_pllv3_type {
 	IMX_PLLV3_GENERIC,
 	IMX_PLLV3_SYS,
 	IMX_PLLV3_USB,
+	IMX_PLLV3_USB_VF610,
 	IMX_PLLV3_AV,
 	IMX_PLLV3_ENET,
 	IMX_PLLV3_MLB,
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 11/28] i.MX: clk: Port imx_clk_gate2_cgr()
From: Andrey Smirnov @ 2016-11-09 16:13 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Update clk-gate2 code to be able to accept arbitrary 'cgr' value and
introduce imx_clk_gate2_cgr() (Used by Vybrid clock tree)

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/clk/imx/clk-gate2.c | 12 +++++++-----
 drivers/clk/imx/clk.h       | 11 +++++++++--
 2 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c
index faed631..f952f3e 100644
--- a/drivers/clk/imx/clk-gate2.c
+++ b/drivers/clk/imx/clk-gate2.c
@@ -26,6 +26,7 @@ struct clk_gate2 {
 	struct clk clk;
 	void __iomem *reg;
 	int shift;
+	u8 cgr_val;
 	const char *parent;
 #define CLK_GATE_INVERTED	(1 << 0)
 	unsigned flags;
@@ -43,7 +44,7 @@ static int clk_gate2_enable(struct clk *clk)
 	if (g->flags & CLK_GATE_INVERTED)
 		val &= ~(3 << g->shift);
 	else
-		val |= 3 << g->shift;
+		val |= g->cgr_val << g->shift;
 
 	writel(val, g->reg);
 
@@ -87,12 +88,13 @@ static struct clk_ops clk_gate2_ops = {
 };
 
 struct clk *clk_gate2_alloc(const char *name, const char *parent,
-		void __iomem *reg, u8 shift)
+			    void __iomem *reg, u8 shift, u8 cgr_val)
 {
 	struct clk_gate2 *g = xzalloc(sizeof(*g));
 
 	g->parent = parent;
 	g->reg = reg;
+	g->cgr_val = cgr_val;
 	g->shift = shift;
 	g->clk.ops = &clk_gate2_ops;
 	g->clk.name = name;
@@ -111,12 +113,12 @@ void clk_gate2_free(struct clk *clk)
 }
 
 struct clk *clk_gate2(const char *name, const char *parent, void __iomem *reg,
-		u8 shift)
+		      u8 shift, u8 cgr_val)
 {
 	struct clk *g;
 	int ret;
 
-	g = clk_gate2_alloc(name , parent, reg, shift);
+	g = clk_gate2_alloc(name , parent, reg, shift, cgr_val);
 
 	ret = clk_register(g);
 	if (ret) {
@@ -133,7 +135,7 @@ struct clk *clk_gate2_inverted(const char *name, const char *parent,
 	struct clk *clk;
 	struct clk_gate2 *g;
 
-	clk = clk_gate2(name, parent, reg, shift);
+	clk = clk_gate2(name, parent, reg, shift, 0x3);
 	if (IS_ERR(clk))
 		return clk;
 
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index c5913e1..2aeb356 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -2,7 +2,7 @@
 #define __IMX_CLK_H
 
 struct clk *clk_gate2(const char *name, const char *parent, void __iomem *reg,
-		u8 shift);
+		      u8 shift, u8 cgr_val);
 
 static inline struct clk *imx_clk_divider(const char *name, const char *parent,
 		void __iomem *reg, u8 shift, u8 width)
@@ -51,9 +51,16 @@ static inline struct clk *imx_clk_gate(const char *name, const char *parent,
 static inline struct clk *imx_clk_gate2(const char *name, const char *parent,
 		void __iomem *reg, u8 shift)
 {
-	return clk_gate2(name, parent, reg, shift);
+	return clk_gate2(name, parent, reg, shift, 0x3);
 }
 
+static inline struct clk *imx_clk_gate2_cgr(const char *name, const char *parent,
+					    void __iomem *reg, u8 shift, u8 cgr_val)
+{
+	return clk_gate2(name, parent, reg, shift, cgr_val);
+}
+
+
 struct clk *imx_clk_pllv1(const char *name, const char *parent,
 		void __iomem *base);
 
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 14/28] i.MX: clk: Port imx_clk_mux_flags from Linux
From: Andrey Smirnov @ 2016-11-09 16:14 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Port imx_clk_mux_flags from Linux, to simplify clock code porting.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/clk/imx/clk.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index fd43fc2..970f65c 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -30,6 +30,14 @@ static inline struct clk *imx_clk_fixed_factor(const char *name,
 	return clk_fixed_factor(name, parent, mult, div, CLK_SET_RATE_PARENT);
 }
 
+static inline struct clk *imx_clk_mux_flags(const char *name, void __iomem *reg,
+					    u8 shift, u8 width,
+					    const char **parents, u8 num_parents,
+					    unsigned long flags)
+{
+	return clk_mux(name, reg, shift, width, parents, num_parents, flags);
+}
+
 static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
 		u8 shift, u8 width, const char **parents, u8 num_parents)
 {
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 05/28] i.MX: Add support for VF610 Tower board
From: Andrey Smirnov @ 2016-11-09 16:13 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Add support for VF610 Tower board.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 arch/arm/boards/Makefile                           |   1 +
 arch/arm/boards/freescale-vf610-twr/Makefile       |   3 +
 .../flash-header-vf610-twr.imxcfg                  | 278 +++++++++++++++++++++
 arch/arm/boards/freescale-vf610-twr/lowlevel.c     |  45 ++++
 arch/arm/dts/Makefile                              |   1 +
 arch/arm/dts/vf610-twr.dts                         |  14 ++
 arch/arm/mach-imx/Kconfig                          |   4 +
 images/Makefile.imx                                |   5 +
 8 files changed, 351 insertions(+)
 create mode 100644 arch/arm/boards/freescale-vf610-twr/Makefile
 create mode 100644 arch/arm/boards/freescale-vf610-twr/flash-header-vf610-twr.imxcfg
 create mode 100644 arch/arm/boards/freescale-vf610-twr/lowlevel.c
 create mode 100644 arch/arm/dts/vf610-twr.dts

diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
index 1a0f63f..ff0a86f 100644
--- a/arch/arm/boards/Makefile
+++ b/arch/arm/boards/Makefile
@@ -140,3 +140,4 @@ obj-$(CONFIG_MACH_ZYLONITE)			+= zylonite/
 obj-$(CONFIG_MACH_VARISCITE_MX6)		+= variscite-mx6/
 obj-$(CONFIG_MACH_VSCOM_BALTOS)			+= vscom-baltos/
 obj-$(CONFIG_MACH_QEMU_VIRT64)			+= qemu-virt64/
+obj-$(CONFIG_MACH_VF610_TWR)			+= freescale-vf610-twr/
diff --git a/arch/arm/boards/freescale-vf610-twr/Makefile b/arch/arm/boards/freescale-vf610-twr/Makefile
new file mode 100644
index 0000000..6b029ce
--- /dev/null
+++ b/arch/arm/boards/freescale-vf610-twr/Makefile
@@ -0,0 +1,3 @@
+obj-y += flash-header-vf610-twr.dcd.o
+extra-y += flash-header-vf610-twr.dcd.S flash-header-vf610-twr.dcd
+lwl-y += lowlevel.o
diff --git a/arch/arm/boards/freescale-vf610-twr/flash-header-vf610-twr.imxcfg b/arch/arm/boards/freescale-vf610-twr/flash-header-vf610-twr.imxcfg
new file mode 100644
index 0000000..01ffc69
--- /dev/null
+++ b/arch/arm/boards/freescale-vf610-twr/flash-header-vf610-twr.imxcfg
@@ -0,0 +1,278 @@
+soc vf610
+loadaddr 0x80000000
+dcdofs 0x400
+
+#define VF610_DDR_PAD_CTRL	0x00000180 /* 25 Ohm drive strength */
+#define VF610_DDR_PAD_CTRL_1	0x00010180 /* 25 Ohm drive strength + differential input */
+
+#define DDRMC_PHY_DQ_TIMING	0x00002613
+#define DDRMC_PHY_DQS_TIMING	0x00002615
+#define DDRMC_PHY_CTRL		0x00210000
+#define DDRMC_PHY_MASTER_CTRL	0x0001012a
+#define DDRMC_PHY_SLAVE_CTRL	0x00002000
+#define DDRMC_PHY_OFF		0x00000000
+#define DDRMC_PHY_PROC_PAD_ODT	0x00010101
+
+#ifdef DEBUG
+#define CHECKPOINT(n) wm 32 0x3f040000 n
+#else
+#define CHECKPOINT(n)
+#endif
+
+CHECKPOINT(1)
+
+/* ======================= Clock initialization =======================*/
+
+/*
+ * Ungate all IP block clocks
+ */
+wm 32 0x4006b040 0xffffffff
+wm 32 0x4006b044 0xffffffff
+wm 32 0x4006b048 0xffffffff
+wm 32 0x4006b04c 0xffffffff
+wm 32 0x4006b050 0xffffffff
+wm 32 0x4006b058 0xffffffff
+wm 32 0x4006b05c 0xffffffff
+wm 32 0x4006b060 0xffffffff
+wm 32 0x4006b064 0xffffffff
+wm 32 0x4006b068 0xffffffff
+wm 32 0x4006b06c 0xffffffff
+
+
+/*
+ * We have to options to clock DDR controller:
+ *
+ *  - Use Core-A5 clock
+ *  - Use PLL2 PFD2 clock
+ *
+
+ * Using first option without changing PLL settings doesn't seem to be
+ * possible given that DDRMC requires minimum of 300Mhz and MaskROM
+ * configures it to be clocked at 264Mhz. Changing PLL1 settings
+ * proved to be challenging becuase MaskROM code executing this DCD
+ * will also be fetching the rest of the bootloader via some
+ * peripheral interface whose clock is derived from Cortex-A5 clock.
+ *
+ * As a result this DCD configuration code uses the second option of
+ * clocking DDR wiht PLL2 PFD2 clock output
+ *
+ * Turn PLL2 on
+ */
+wm 32 0x40050030 0x00002001 /* Fout = Fin * 22 */
+
+CHECKPOINT(2)
+
+/*
+ * Wait for PLLs to lock
+ */
+check 32 while_any_bit_clear 0x40050030 0x80000000
+
+
+CHECKPOINT(3)
+
+/*
+ * Switch DDRMC to be clocked with PLL2 PFD2 and enable PFD2 output
+ */
+clear_bits 32 0x4006b008 0x00000040
+set_bits   32 0x4006b008 0x00002000
+
+
+
+/* ======================= DDR IOMUX ======================= */
+
+CHECKPOINT(4)
+
+wm 32 0x40048220 VF610_DDR_PAD_CTRL
+wm 32 0x40048224 VF610_DDR_PAD_CTRL
+wm 32 0x40048228 VF610_DDR_PAD_CTRL
+wm 32 0x4004822c VF610_DDR_PAD_CTRL
+wm 32 0x40048230 VF610_DDR_PAD_CTRL
+wm 32 0x40048234 VF610_DDR_PAD_CTRL
+wm 32 0x40048238 VF610_DDR_PAD_CTRL
+wm 32 0x4004823c VF610_DDR_PAD_CTRL
+wm 32 0x40048240 VF610_DDR_PAD_CTRL
+wm 32 0x40048244 VF610_DDR_PAD_CTRL
+wm 32 0x40048248 VF610_DDR_PAD_CTRL
+wm 32 0x4004824c VF610_DDR_PAD_CTRL
+wm 32 0x40048250 VF610_DDR_PAD_CTRL
+wm 32 0x40048254 VF610_DDR_PAD_CTRL
+wm 32 0x40048258 VF610_DDR_PAD_CTRL
+wm 32 0x4004825c VF610_DDR_PAD_CTRL
+wm 32 0x40048260 VF610_DDR_PAD_CTRL
+wm 32 0x40048264 VF610_DDR_PAD_CTRL
+wm 32 0x40048268 VF610_DDR_PAD_CTRL
+wm 32 0x4004826c VF610_DDR_PAD_CTRL
+wm 32 0x40048270 VF610_DDR_PAD_CTRL
+wm 32 0x40048274 VF610_DDR_PAD_CTRL
+wm 32 0x40048278 VF610_DDR_PAD_CTRL
+wm 32 0x4004827c VF610_DDR_PAD_CTRL_1
+wm 32 0x40048280 VF610_DDR_PAD_CTRL_1
+wm 32 0x40048284 VF610_DDR_PAD_CTRL_1
+wm 32 0x40048288 VF610_DDR_PAD_CTRL_1
+wm 32 0x4004828c VF610_DDR_PAD_CTRL_1
+wm 32 0x40048290 VF610_DDR_PAD_CTRL_1
+wm 32 0x40048294 VF610_DDR_PAD_CTRL_1
+wm 32 0x40048298 VF610_DDR_PAD_CTRL_1
+wm 32 0x4004829c VF610_DDR_PAD_CTRL_1
+wm 32 0x400482a0 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482a4 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482a8 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482ac VF610_DDR_PAD_CTRL_1
+wm 32 0x400482b0 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482b4 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482b8 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482bc VF610_DDR_PAD_CTRL_1
+wm 32 0x400482c0 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482c4 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482c8 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482cc VF610_DDR_PAD_CTRL
+wm 32 0x400482d0 VF610_DDR_PAD_CTRL
+wm 32 0x400482d4 VF610_DDR_PAD_CTRL
+wm 32 0x400482d8 VF610_DDR_PAD_CTRL
+wm 32 0x4004821c VF610_DDR_PAD_CTRL
+
+/* ======================= DDR Controller =======================*/
+
+CHECKPOINT(5)
+
+wm 32 0x400ae000 0x00000600
+wm 32 0x400ae008 0x00000020
+wm 32 0x400ae028 0x00013880
+wm 32 0x400ae02c 0x00030d40
+wm 32 0x400ae030 0x0000050c
+wm 32 0x400ae034 0x15040400
+wm 32 0x400ae038 0x1406040f
+wm 32 0x400ae040 0x04040000
+wm 32 0x400ae044 0x006db00c
+wm 32 0x400ae048 0x00000403
+wm 32 0x400ae050 0x01000000
+wm 32 0x400ae054 0x00060001
+wm 32 0x400ae058 0x000c0000
+wm 32 0x400ae05c 0x03000200
+wm 32 0x400ae060 0x00000006
+wm 32 0x400ae064 0x00010000
+wm 32 0x400ae068 0x0c30002c
+wm 32 0x400ae070 0x00000000
+wm 32 0x400ae074 0x00000003
+wm 32 0x400ae078 0x0000000a
+wm 32 0x400ae07c 0x003001d4
+wm 32 0x400ae084 0x00010000
+wm 32 0x400ae088 0x00050500
+wm 32 0x400ae098 0x00000000
+wm 32 0x400ae09c 0x04001002
+wm 32 0x400ae0a4 0x00000001
+wm 32 0x400ae0c0 0x00460420
+wm 32 0x400ae108 0x01000200
+wm 32 0x400ae10c 0x00000040
+wm 32 0x400ae114 0x00000200
+wm 32 0x400ae118 0x00000040
+wm 32 0x400ae120 0x00000000
+wm 32 0x400ae124 0x0a010300
+wm 32 0x400ae128 0x01014040
+wm 32 0x400ae12c 0x01010101
+wm 32 0x400ae130 0x03030100
+wm 32 0x400ae134 0x01000101
+wm 32 0x400ae138 0x0700000c
+wm 32 0x400ae13c 0x00000000
+wm 32 0x400ae148 0x10000000
+wm 32 0x400ae15c 0x01000000
+wm 32 0x400ae160 0x00040000
+wm 32 0x400ae164 0x00000002
+wm 32 0x400ae16c 0x00020000
+wm 32 0x400ae180 0x00002819
+wm 32 0x400ae184 0x01000000
+wm 32 0x400ae188 0x00000000
+wm 32 0x400ae18c 0x00000000
+wm 32 0x400ae198 0x00010100
+wm 32 0x400ae1a4 0x00000000
+wm 32 0x400ae1a8 0x00000004
+wm 32 0x400ae1b8 0x00040000
+wm 32 0x400ae1c8 0x00000000
+wm 32 0x400ae1cc 0x00000000
+wm 32 0x400ae1d4 0x00000000
+wm 32 0x400ae1d8 0x01010000
+wm 32 0x400ae1e0 0x02020000
+wm 32 0x400ae1e4 0x00000202
+wm 32 0x400ae1e8 0x01010064
+wm 32 0x400ae1ec 0x00010101
+wm 32 0x400ae1f0 0x00000064
+wm 32 0x400ae1f8 0x00000800
+wm 32 0x400ae210 0x00000506
+wm 32 0x400ae224 0x00020000
+wm 32 0x400ae228 0x01000000
+wm 32 0x400ae22c 0x04070303
+wm 32 0x400ae230 0x00000040
+wm 32 0x400ae23c 0x06000080
+wm 32 0x400ae240 0x04070303
+wm 32 0x400ae244 0x00000040
+wm 32 0x400ae248 0x00000040
+wm 32 0x400ae24c 0x000f0000
+wm 32 0x400ae250 0x000f0000
+wm 32 0x400ae25c 0x00000101
+wm 32 0x400ae268 0x682c4000
+wm 32 0x400ae26c 0x00000012
+wm 32 0x400ae278 0x00000006
+wm 32 0x400ae284 0x00010202
+
+/* ======================= DDR PHY =======================*/
+
+CHECKPOINT(6)
+
+wm 32 0x400ae400 DDRMC_PHY_DQ_TIMING
+wm 32 0x400ae440 DDRMC_PHY_DQ_TIMING
+wm 32 0x400ae480 DDRMC_PHY_DQ_TIMING
+wm 32 0x400ae404 DDRMC_PHY_DQS_TIMING
+wm 32 0x400ae444 DDRMC_PHY_DQS_TIMING
+wm 32 0x400ae408 DDRMC_PHY_CTRL
+wm 32 0x400ae448 DDRMC_PHY_CTRL
+wm 32 0x400ae488 DDRMC_PHY_CTRL
+wm 32 0x400ae40c DDRMC_PHY_MASTER_CTRL
+wm 32 0x400ae44c DDRMC_PHY_MASTER_CTRL
+wm 32 0x400ae48c DDRMC_PHY_MASTER_CTRL
+wm 32 0x400ae410 DDRMC_PHY_SLAVE_CTRL
+wm 32 0x400ae450 DDRMC_PHY_SLAVE_CTRL
+wm 32 0x400ae490 DDRMC_PHY_SLAVE_CTRL
+wm 32 0x400ae4c4 DDRMC_PHY_OFF
+wm 32 0x400ae4c8 0x00001100
+wm 32 0x400ae4d0 DDRMC_PHY_PROC_PAD_ODT
+
+wm 32 0x400ae000 0x00000601
+
+CHECKPOINT(7)
+
+check 32 while_any_bit_clear 0x400ae140 0x100
+
+CHECKPOINT(8)
+
+/*
+ * Cargo cult DDR controller initialization here we come!
+ *
+ * Experemintation with VF610 Tower Board shows that without the
+ * following code the board would not boot off of SD card when
+ * power-cycled. It will however happily boot when reset via SW3/Reset
+ * button. For whatever reason the following actions appear to be
+ * necessary:
+ *
+ *          - Initialize DDRMC as usual
+ *	    - Issue a read to location in DDR address space
+ *	    - Disable DDRMC
+ *	    - Enable DDRMC and wait for it to finish initializing
+ *
+ * I am sure this is all going to be extrememly embarrassing to read
+ * if/when the real problem and real solution is found.
+ */
+
+/*
+ * Because there's no standalone read command what we do here instead
+ * is write a pattern to memory and then checking that memory address
+ * against that pattern
+ */
+wm 32 0x80000000 0xa5a5a5a5
+check 32 while_any_bit_clear 0x80000000 0xa5a5a5a5
+
+wm 32 0x400ae000 0x00000600
+wm 32 0x400ae000 0x00000601
+
+check 32 while_any_bit_clear 0x400ae140 0x100
+
+CHECKPOINT(9)
\ No newline at end of file
diff --git a/arch/arm/boards/freescale-vf610-twr/lowlevel.c b/arch/arm/boards/freescale-vf610-twr/lowlevel.c
new file mode 100644
index 0000000..6504273
--- /dev/null
+++ b/arch/arm/boards/freescale-vf610-twr/lowlevel.c
@@ -0,0 +1,45 @@
+#include <common.h>
+#include <linux/sizes.h>
+#include <mach/generic.h>
+#include <asm/barebox-arm-head.h>
+#include <asm/barebox-arm.h>
+#include <mach/vf610-regs.h>
+#include <mach/clock-vf610.h>
+#include <mach/iomux-vf610.h>
+#include <debug_ll.h>
+
+static inline void setup_uart(void)
+{
+	void __iomem *iomuxbase = IOMEM(VF610_IOMUXC_BASE_ADDR);
+
+	vf610_ungate_all_peripherals();
+
+	/*
+	 * VF610_PAD_PTB4__UART1_TX
+	 */
+	writel(VF610_UART_PAD_CTRL | (2 << 20), iomuxbase + 0x0068);
+	writel(0, iomuxbase + 0x0380);
+
+	vf610_uart_setup_ll();
+}
+
+extern char __dtb_vf610_twr_start[];
+
+ENTRY_FUNCTION(start_vf610_twr, r0, r1, r2)
+{
+	int i;
+	void *fdt;
+	void __iomem *mscm = IOMEM(VF610_MSCM_BASE_ADDR);
+
+	vf610_cpu_lowlevel_init();
+
+	for (i = 0; i < VF610_MSCM_IRSPRC_NUM; i++)
+		writew(VF610_MSCM_IRSPRC_CP0_EN,
+		       mscm + VF610_MSCM_IRSPRC(i));
+
+	if (IS_ENABLED(CONFIG_DEBUG_LL))
+		setup_uart();
+
+	fdt = __dtb_vf610_twr_start - get_runtime_offset();
+	barebox_arm_entry(0x80000000, SZ_128M, fdt);
+}
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 8d8d1fb..607c620 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -78,5 +78,6 @@ pbl-dtb-$(CONFIG_MACH_UDOO) += imx6q-udoo.dtb.o
 pbl-dtb-$(CONFIG_MACH_USI_TOPKICK) += kirkwood-topkick-bb.dtb.o
 pbl-dtb-$(CONFIG_MACH_VARISCITE_MX6) += imx6q-var-custom.dtb.o
 pbl-dtb-$(CONFIG_MACH_VSCOM_BALTOS) += am335x-baltos-minimal.dtb.o
+pbl-dtb-$(CONFIG_MACH_VF610_TWR) += vf610-twr.dtb.o
 
 clean-files := *.dtb *.dtb.S .*.dtc .*.pre .*.dts *.dtb.lzo
diff --git a/arch/arm/dts/vf610-twr.dts b/arch/arm/dts/vf610-twr.dts
new file mode 100644
index 0000000..54b4435
--- /dev/null
+++ b/arch/arm/dts/vf610-twr.dts
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <arm/vf610-twr.dts>
+
+&usbdev0 {
+	status = "disabled";
+};
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index cfbaaa2..5f4fdc6 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -337,6 +337,10 @@ config MACH_CM_FX6
 	bool "CM FX6"
 	select ARCH_IMX6
 
+config MACH_VF610_TWR
+	bool "Freescale VF610 Tower Board"
+	select ARCH_VF610
+
 endif
 
 # ----------------------------------------------------------
diff --git a/images/Makefile.imx b/images/Makefile.imx
index 8db9c75..983d896 100644
--- a/images/Makefile.imx
+++ b/images/Makefile.imx
@@ -403,3 +403,8 @@ pblx-$(CONFIG_MACH_ELTEC_HIPERCAM) += start_imx6dl_eltec_hipercam
 CFG_start_imx6dl_eltec_hipercam.pblx.imximg = $(board)/eltec-hipercam/flash-header-eltec-hipercam.imxcfg
 FILE_barebox-eltec-hipercam.img = start_imx6dl_eltec_hipercam.pblx.imximg
 image-$(CONFIG_MACH_ELTEC_HIPERCAM) += barebox-eltec-hipercam.img
+
+pblx-$(CONFIG_MACH_VF610_TWR) += start_vf610_twr
+CFG_start_vf610_twr.pblx.imximg = $(board)/freescale-vf610-twr/flash-header-vf610-twr.imxcfg
+FILE_barebox-vf610-twr.img = start_vf610_twr.pblx.imximg
+image-$(CONFIG_MACH_VF610_TWR) += barebox-vf610-twr.img
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related


This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.