Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* emmc on imx6 sabresd
From: Philippe De Muyter @ 2014-01-29 10:03 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Shawn,

I try to use the emmc on my sabresd board and on a similar custom board
using 3.13, and I have just discovered by reading Internet that it was
not supported up to some weeks ago.  Is there a git tree somewhere that
has a branch containing 3.13 or linux-next and all the fixes for emmc on
sabresd ?

TIA

-- 
Philippe De Muyter +32 2 6101532 Macq SA rue de l'Aeronef 2 B-1140 Bruxelles

^ permalink raw reply

* [PATCH 05/18] mfd: max14577: Use of_match_ptr() in i2c_driver
From: Krzysztof Kozlowski @ 2014-01-29 10:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390911522-28209-6-git-send-email-k.kozlowski@samsung.com>

I would like to drop this patch.

It does not make sense as "max14577_dt_match" is always compiled and
of_match_ptr was removed on purpose by Sachin Kamat (ae679c12e8; mfd:
max14577: Remove redundant of_match_ptr helper).

Best regards,
Krzysztof Kozlowski


On Tue, 2014-01-28 at 13:18 +0100, Krzysztof Kozlowski wrote:
> Use of_match_ptr() in assignment of i2c_driver.of_match_table.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
> Cc: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
>  drivers/mfd/max14577.c |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c
> index 2ac2f2d7cea6..75b37082a3fe 100644
> --- a/drivers/mfd/max14577.c
> +++ b/drivers/mfd/max14577.c
> @@ -224,7 +224,7 @@ static struct i2c_driver max14577_i2c_driver = {
>  		.name = "max14577",
>  		.owner = THIS_MODULE,
>  		.pm = &max14577_pm,
> -		.of_match_table = max14577_dt_match,
> +		.of_match_table = of_match_ptr(max14577_dt_match),
>  	},
>  	.probe = max14577_i2c_probe,
>  	.remove = max14577_i2c_remove,

^ permalink raw reply

* [RFC PATCH 0/9] mtd: nand: add sunxi NAND Flash Controller support
From: boris brezillon @ 2014-01-29 10:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAL_JsqJNd_gtn-cCLbZxT=s5NkkXp0DZkJkZrBhWiaL6Js=woQ@mail.gmail.com>

Hello Rob,

On 23/01/2014 16:22, Rob Herring wrote:
> On Sat, Jan 11, 2014 at 7:38 AM, boris brezillon
> <b.brezillon@overkiz.com> wrote:
>> On 08/01/2014 15:21, Boris BREZILLON wrote:
>>> Hello,
>>>
>>> This series add the sunxi NFC support with up to 8 NAND chip connected.
>>> I'm still in the early stages drivers development and some key features
>>> are
>>> missing, but it's usable (I tested it on the cubietruck board).
>>>
>>> Here's what's missing:
>>>    - HW ECC support
>>>    - DMA support
>>>    - HW randomization support
>>>    - many more improvements
>>>
>>> This series depends on Emilio's patch series implementing mod0 clks
>>>
>>> (http://lists.infradead.org/pipermail/linux-arm-kernel/2013-July/185478.html)
>>> + an other patch not yet posted
>>>
>>> (http://git.elopez.com.ar/linux/commits/5b4eb3ac406b9c98965714d40e8dd6da943d1ab0)
>>
>> During my reasearch regarding the HW ECC and HW randomizer of the Allwinner
>> NAND flash controller I found this document describing the Altera NAND flash
>> controller
>> (which is in turn based on a cadence IP):
> Which may be similar to drivers/mtd/nand/denali.c as Cadence bought Denali?
Actually I was wrong, the sunxi and the cadence IP have nothing in common.
This was pointed out by Henrik (see this thread :
https://groups.google.com/forum/#!searchin/linux-sunxi/nand/linux-sunxi/x69tFBi95Zk/bNyJlWWOV8oJ 
<https://groups.google.com/forum/#%21searchin/linux-sunxi/nand/linux-sunxi/x69tFBi95Zk/bNyJlWWOV8oJ>).


Sorry for the false hopes.

Best Regards,

Boris

>
> Rob

^ permalink raw reply

* [PATCH RESEND 1/4] clk: clk-s2mps11: Refactor for including support for  other MFD clocks
From: Krzysztof Kozlowski @ 2014-01-29 10:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <mvd17-4vW-3@gated-at.bofh.it>

Hi,

> 
> Quoting Mark Brown (2013-12-31 08:09:16)
> > On Mon, Dec 30, 2013 at 09:33:50AM +0530, Tushar Behera wrote:
> > 
> > > Commit 1b1ccee1e821 "mfd: s2mps11: Fix build after regmap field rename
> > > in sec-core.c" is also touching this file, which is in Mark's tree
> > > right now. If I rebase
> > 
> > It's been in Linus' tree for a while now.
> 
> OK, so I merged the two patches into clk-next, then merged clk-next into
> next-20131224 and the merge is super trivial to resolve. So I propose
> that we just let it get resolved in linux-next the usual way.
> 
> Any objections? If not I'll take these two patches into clk-next.

Did you merged these patches into clk-next? Unfortunately I couldn't
find them (clk-next, next).

I am asking because I want to send patches with support for S2MPS14
clock (based on these patches).

Best regards,
Krzysztof

^ permalink raw reply

* [RFC PATCH 1/9] mtd: nand: retrieve ECC requirements from Hynix READ ID byte 4
From: boris brezillon @ 2014-01-29 10:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140123014906.GY8919@ld-irv-0074>

Hello Brian,

On 23/01/2014 02:49, Brian Norris wrote:
> + Huang
>
> Hi Boris,
>
> On Wed, Jan 08, 2014 at 03:21:56PM +0100, Boris BREZILLON wrote:
>> The Hynix nand flashes store their ECC requirements in byte 4 of its id
>> (returned on READ ID command).
>>
>> Signed-off-by: Boris BREZILLON <b.brezillon@overkiz.com>
> I haven't verified yet (perhaps Huang can confirm?), but this may be
> similar to a patch Huang submitted recently. In his case, we found that
> this table is actually quite unreliable and is likely hard to maintain.

You mean these bytes are not reliable within the whole Hynix LP (Large Page)
NAND product line ?

>
> Why do you need this ECC information, for my reference?

Because the NAND flash available on the cubietruck board does not 
support the
ONFI standard, and I thought this could be a option to retrieve the ECC 
strength
requirements.

Anyway, I added a new helper function to retrieve ecc informations from 
device
tree (I'll post it in the 2nd version of this series). We'll see if this 
approach is
accepted...

>
> Brian

^ permalink raw reply

* [PATCH v2] ARM: mm: Fix stage-2 device memory attributes
From: Marc Zyngier @ 2014-01-29 10:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390944264-3435-1-git-send-email-christoffer.dall@linaro.org>

On 28/01/14 21:24, Christoffer Dall wrote:
> The stage-2 memory attributes are distinct from the Hyp memory
> attributes and the Stage-1 memory attributes.  We were using the stage-1
> memory attributes for stage-2 mappings causing device mappings to be
> mapped as normal memory.  Add the S2 equivalent defines for memory
> attributes and fix the comments explaining the defines while at it.
> 
> Add a prot_pte_s2 field to the mem_type struct and fill out the field
> for device mappings accordingly.
> 
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

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

^ permalink raw reply

* [PATCH 2/9] ARM: dts: imx6sl: remove the use of pingrp macros
From: Heiko Stübner @ 2014-01-29 10:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140128112047.GC20583@S2101-09.ap.freescale.net>

On Tuesday, 28. January 2014 19:20:49 Shawn Guo wrote:
> On Tue, Jan 28, 2014 at 11:17:22AM +0100, Heiko St?bner wrote:
> > [... and so on for the other groups ... ]
> > 
> > I'm confused now :-) . Current linux-next [0] shows the pin-settings as
> > part of imx6sl.dtsi - a way a lot of other architectures organize their
> > pingroups too, with the board file only referencing the relevant
> > pingroups from the predefined ones of the soc.
> > 
> > So I guess your move to the pingrp-header moved them out of the
> > imx6sl.dtsi to the .h and is not part of linux-next;
> 
> Yes, my for-next branch was excluded from linux-next temporarily for
> some reason.  I will ask Stephen to add it back once v3.14-rc1 is out.
> That said, you can see nothing we developed in this cycle on linux-next
> for now.
> 
> > but this patch (and the others in this
> > series) now moves the definitions into the individual board files. Can't
> > you just move them back to the soc-dtsi files to prevent each board
> > duplicating them?
> 
> No.  That will bring back the problem we try to solve from the
> beginning [1].
>
> [1] http://thread.gmane.org/gmane.linux.ports.arm.kernel/275912/

Thanks for the pointer, I think I understand the issue now :-) .

So for the short term, I should probably also define the pingroups in my board-
dts then.


But as an insane idea that I just had, because the issue will probably affect 
more architectures at some point when their pingroups or other common-nodes 
grow, how about introducing something like a "/delete-if-unreferenced/" prefix 
in dtc?

As I could see in [0], adding something to dtc is not as far off as I thought.

In essence one would add the pingroups to the soc dtsi, like

		ecspi1 {
			/delete-if-unreferenced/ pinctrl_ecspi1_1: ecspi1grp-1 {
				fsl,pins = <
					MX6SL_PAD_ECSPI1_MISO__ECSPI1_MISO 0x100b1
					MX6SL_PAD_ECSPI1_MOSI__ECSPI1_MOSI 0x100b1
					MX6SL_PAD_ECSPI1_SCLK__ECSPI1_SCLK 0x100b1
				>;
			};
		};

and dtc would then be tasked with checking if the node gets referenced in a 
phandle somewhere in the dts and if not removing it.

I don't know if this is at all sane to think about or doable in dtc.


Heiko

[0] http://www.spinics.net/lists/arm-kernel/msg300936.html

^ permalink raw reply

* [PATCH v9 1/6] arm64: Add macros to manage processor debug state
From: Will Deacon @ 2014-01-29 10:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390908022-10287-2-git-send-email-vijay.kilari@gmail.com>

On Tue, Jan 28, 2014 at 11:20:17AM +0000, vijay.kilari at gmail.com wrote:
> From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
> 
> Add macros to enable and disable to manage PSTATE.D
> for debugging. The macros local_dbg_save and local_dbg_restore
> are moved to irqflags.h file
> 
> KGDB boot tests fail because of PSTATE.D is masked.
> unmask it for debugging support
> 
> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>

Acked-by: Will Deacon <will.deacon@arm.com>

Cheers,

Will

^ permalink raw reply

* [PATCH 11/11] arm: dma-mapping: Add support to extend DMA IOMMU mappings
From: Marek Szyprowski @ 2014-01-29 10:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389876263-25759-12-git-send-email-andreas.herrmann@calxeda.com>

Hello,

I'm sorry for so late reply, but I was quite busy with other stuff.

On 2014-01-16 13:44, Andreas Herrmann wrote:
> Instead of using just one bitmap to keep track of IO virtual addresses
> (handed out for IOMMU use) introduce a list of iova_ranges (each
> having its own bitmap). This allows us to extend existing mappings
> when running out of iova space for a mapping.
>
> If there is not enough space in the mapping to service an IO virtual
> address allocation request, __alloc_iova() tries to extend the mapping
> -- by allocating another bitmap -- and makes another allocation
> attempt using the freshly allocated bitmap.
>
> This allows arm iommu drivers to start with a decent initial size when
> an dma_iommu_mapping is created and still to avoid running out of IO
> virtual addresses for the mapping.
>
> Tests were done on Calxeda ECX-2000 with smmu for sata and xgmac.
> I've used SZ_512K both for initial mapping size and grow_size.

Thanks for implementing this feature! I remember it was discussed from
early beginning of arm dma iommu support, but I never had enough time
to actually implement it. I briefly checked the code and it look fine,
however I really wonder if we need separate grow_size parameter?
Personally I would simplify it to simply grow the bitmap by initial
size until it reaches the maximal size.

The whole concept of the simplified bitmap (where 1 bit != 1 page) for
iova allocation is a specific feature of this code and it has nothing
to the hardware. After thinking a bit more on the existing
implementation I've already observed that it is sometimes hard to
understand the parameters for arm_iommu_create_mapping() function,
especially the 'order' argument is ofter misunderstood. With your
patch we got two additional parameters. Maybe it will be much better
to use only 2 arguments: max_mapping_size and allocation_accuracy.
The initial bitmap size can be then calculated to fit it into single
memory page (that's quite important to avoid allocations larger that
a single memory page). 'allocation_accuracy' will serve the same way
as 'order' parameter now (but expressed in bytes rather than being
the multiplier for the number of pages). This way the
arm_iommu_create_mapping() function should be much easier to
understand, while keeping the implementation details hidden from the
caller.

> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Marek Szyprowski <m.szyprowski@samsung.com>
> Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
> Cc: Hiroshi Doyu <hdoyu@nvidia.com>
> Cc: Andreas Herrmann <herrmann.der.user@googlemail.com>
> Signed-off-by: Andreas Herrmann <andreas.herrmann@calxeda.com>
> ---
>   arch/arm/include/asm/dma-iommu.h |   17 ++++-
>   arch/arm/mm/dma-mapping.c        |  147 ++++++++++++++++++++++++++++++++------
>   2 files changed, 139 insertions(+), 25 deletions(-)
>
> diff --git a/arch/arm/include/asm/dma-iommu.h b/arch/arm/include/asm/dma-iommu.h
> index 50edacd..987d62c 100644
> --- a/arch/arm/include/asm/dma-iommu.h
> +++ b/arch/arm/include/asm/dma-iommu.h
> @@ -8,15 +8,26 @@
>   #include <linux/dma-debug.h>
>   #include <linux/kmemcheck.h>
>   #include <linux/kref.h>
> +#include <linux/list.h>
> +
> +struct dma_iommu_iova_range {
> +	struct list_head	list_head;
> +	unsigned long		*bitmap;
> +	size_t			bits;
> +	dma_addr_t		base;
> +	dma_addr_t		size;
> +};
>   
>   struct dma_iommu_mapping {
>   	/* iommu specific data */
>   	struct iommu_domain	*domain;
>   
> -	void			*bitmap;
> -	size_t			bits;
> -	unsigned int		order;
> +	struct list_head	iova_ranges;
>   	dma_addr_t		base;
> +	dma_addr_t		size;
> +	dma_addr_t		grow_size;
> +	dma_addr_t		max_size;
> +	unsigned int		order;
>   
>   	spinlock_t		lock;
>   	struct kref		kref;
> diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
> index ccea46a..503e8d6 100644
> --- a/arch/arm/mm/dma-mapping.c
> +++ b/arch/arm/mm/dma-mapping.c
> @@ -26,6 +26,7 @@
>   #include <linux/io.h>
>   #include <linux/vmalloc.h>
>   #include <linux/sizes.h>
> +#include <linux/list.h>
>   
>   #include <asm/memory.h>
>   #include <asm/highmem.h>
> @@ -1069,6 +1070,8 @@ fs_initcall(dma_debug_do_init);
>   
>   /* IOMMU */
>   
> +static int extend_iommu_mapping(struct dma_iommu_mapping *mapping);
> +
>   static inline dma_addr_t __alloc_iova(struct dma_iommu_mapping *mapping,
>   				      size_t size)
>   {
> @@ -1076,6 +1079,8 @@ static inline dma_addr_t __alloc_iova(struct dma_iommu_mapping *mapping,
>   	unsigned int align = 0;
>   	unsigned int count, start;
>   	unsigned long flags;
> +	struct dma_iommu_iova_range *e;
> +	bool area_found;
>   
>   	if (order > CONFIG_ARM_DMA_IOMMU_ALIGNMENT)
>   		order = CONFIG_ARM_DMA_IOMMU_ALIGNMENT;
> @@ -1086,32 +1091,80 @@ static inline dma_addr_t __alloc_iova(struct dma_iommu_mapping *mapping,
>   	if (order > mapping->order)
>   		align = (1 << (order - mapping->order)) - 1;
>   
> +	area_found = false;
>   	spin_lock_irqsave(&mapping->lock, flags);
> -	start = bitmap_find_next_zero_area(mapping->bitmap, mapping->bits, 0,
> -					   count, align);
> -	if (start > mapping->bits) {
> -		spin_unlock_irqrestore(&mapping->lock, flags);
> -		return DMA_ERROR_CODE;
> +	list_for_each_entry(e, &mapping->iova_ranges, list_head) {
> +		start = bitmap_find_next_zero_area(e->bitmap, e->bits, 0,
> +						count, align);
> +		if (start > e->bits)
> +			continue;
> +
> +		bitmap_set(e->bitmap, start, count);
> +		area_found = true;
> +		break;
>   	}
>   
> -	bitmap_set(mapping->bitmap, start, count);
> +	/*
> +	 * Try to extend the existing mapping and perform a second
> +	 * attempt to reserve an IO virtual address range of size
> +	 * bytes.
> +	 */
> +	if (!area_found) {
> +		if (extend_iommu_mapping(mapping)) {
> +			spin_unlock_irqrestore(&mapping->lock, flags);
> +			return DMA_ERROR_CODE;
> +		}
> +		e = list_entry(mapping->iova_ranges.prev,
> +			struct dma_iommu_iova_range, list_head);
> +		start = bitmap_find_next_zero_area(e->bitmap, e->bits, 0,
> +						count, align);
> +		if (start > e->bits) {
> +			spin_unlock_irqrestore(&mapping->lock, flags);
> +			return DMA_ERROR_CODE;
> +		}
> +		bitmap_set(e->bitmap, start, count);
> +	}
>   	spin_unlock_irqrestore(&mapping->lock, flags);
>   
> -	return mapping->base + (start << (mapping->order + PAGE_SHIFT));
> +	return e->base + (start << (mapping->order + PAGE_SHIFT));
>   }
>   
>   static inline void __free_iova(struct dma_iommu_mapping *mapping,
>   			       dma_addr_t addr, size_t size)
>   {
> -	unsigned int start = (addr - mapping->base) >>
> -			     (mapping->order + PAGE_SHIFT);
> -	unsigned int count = ((size >> PAGE_SHIFT) +
> -			      (1 << mapping->order) - 1) >> mapping->order;
> +	struct dma_iommu_iova_range *e;
> +	unsigned int start, count, tmp;
>   	unsigned long flags;
>   
> -	spin_lock_irqsave(&mapping->lock, flags);
> -	bitmap_clear(mapping->bitmap, start, count);
> -	spin_unlock_irqrestore(&mapping->lock, flags);
> +	list_for_each_entry(e, &mapping->iova_ranges, list_head) {
> +		if (!size)
> +			break;
> +		if ((addr < e->base) || (addr >= e->base + e->size))
> +			continue;
> +
> +		start = (addr - e->base) >> (mapping->order + PAGE_SHIFT);
> +		if (addr + size > e->base + e->size) {
> +			/*
> +			 * The address range to be freed crosses an
> +			 * iova_range boundary.
> +			 * Hence calc count parameter to fit within
> +			 * current iova_range and prepare addr and
> +			 * size for next iteration.
> +			 */
> +			tmp = (e->base + e->size) - addr;
> +			count = ((tmp >> PAGE_SHIFT) +
> +				(1 << mapping->order) - 1) >> mapping->order;
> +			size -= tmp;
> +			addr += tmp;
> +		} else {
> +			count = ((size >> PAGE_SHIFT) +
> +				(1 << mapping->order) - 1) >> mapping->order;
> +			size -= size;
> +		}
> +		spin_lock_irqsave(&mapping->lock, flags);
> +		bitmap_clear(e->bitmap, start, count);
> +		spin_unlock_irqrestore(&mapping->lock, flags);
> +	}
>   }
>   
>   static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
> @@ -1892,6 +1945,7 @@ arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size,
>   	unsigned int count = size >> (PAGE_SHIFT + order);
>   	unsigned int bitmap_size = BITS_TO_LONGS(count) * sizeof(long);
>   	struct dma_iommu_mapping *mapping;
> +	struct dma_iommu_iova_range *iovar;
>   	int err = -ENOMEM;
>   
>   	if (!count)
> @@ -1901,23 +1955,37 @@ arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size,
>   	if (!mapping)
>   		goto err;
>   
> -	mapping->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
> -	if (!mapping->bitmap)
> +	INIT_LIST_HEAD(&mapping->iova_ranges);
> +	spin_lock_init(&mapping->lock);
> +
> +	iovar = kzalloc(sizeof(struct dma_iommu_iova_range), GFP_KERNEL);
> +	if (!iovar)
>   		goto err2;
>   
> -	mapping->base = base;
> -	mapping->bits = BITS_PER_BYTE * bitmap_size;
> +	iovar->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
> +	if (!iovar->bitmap)
> +		goto err3;
> +
> +	iovar->bits = BITS_PER_BYTE * bitmap_size;
> +	list_add_tail(&iovar->list_head, &mapping->iova_ranges);
> +
> +	mapping->base = iovar->base = base;
> +	mapping->size = iovar->size = size;
> +
>   	mapping->order = order;
> -	spin_lock_init(&mapping->lock);
> +	mapping->grow_size = grow_size;
> +	mapping->max_size = max_size;
>   
>   	mapping->domain = iommu_domain_alloc(bus);
>   	if (!mapping->domain)
> -		goto err3;
> +		goto err4;
>   
>   	kref_init(&mapping->kref);
>   	return mapping;
> +err4:
> +	kfree(iovar->bitmap);
>   err3:
> -	kfree(mapping->bitmap);
> +	kfree(iovar);
>   err2:
>   	kfree(mapping);
>   err:
> @@ -1927,14 +1995,49 @@ EXPORT_SYMBOL_GPL(arm_iommu_create_mapping);
>   
>   static void release_iommu_mapping(struct kref *kref)
>   {
> +	struct dma_iommu_iova_range *e, *tmp;
>   	struct dma_iommu_mapping *mapping =
>   		container_of(kref, struct dma_iommu_mapping, kref);
>   
>   	iommu_domain_free(mapping->domain);
> -	kfree(mapping->bitmap);
> +	list_for_each_entry_safe(e, tmp, &mapping->iova_ranges, list_head) {
> +		list_del(&e->list_head);
> +		kfree(e->bitmap);
> +		kfree(e);
> +	}
>   	kfree(mapping);
>   }
>   
> +static int extend_iommu_mapping(struct dma_iommu_mapping *mapping)
> +{
> +	struct dma_iommu_iova_range *iovar;
> +	unsigned int count = mapping->grow_size >> (PAGE_SHIFT + mapping->order);
> +	unsigned int bitmap_size = BITS_TO_LONGS(count) * sizeof(long);
> +
> +	if (!mapping->grow_size ||
> +		(mapping->size + mapping->grow_size) >= mapping->max_size)
> +		return -EINVAL;
> +
> +	iovar = kzalloc(sizeof(struct dma_iommu_iova_range), GFP_ATOMIC);
> +	if (!iovar)
> +		return -ENOMEM;
> +
> +	iovar->bitmap = kzalloc(bitmap_size, GFP_ATOMIC);
> +	if (!iovar->bitmap) {
> +		kfree(iovar);
> +		return -ENOMEM;
> +	}
> +
> +	iovar->bits = BITS_PER_BYTE * bitmap_size;
> +	iovar->base = mapping->base + mapping->size;
> +	iovar->size = mapping->grow_size;
> +
> +	mapping->size += mapping->grow_size;
> +	list_add_tail(&iovar->list_head, &mapping->iova_ranges);
> +
> +	return 0;
> +}
> +
>   void arm_iommu_release_mapping(struct dma_iommu_mapping *mapping)
>   {
>   	if (mapping)

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland

^ permalink raw reply

* [PATCH v3] ARM: hw_breakpoint: Add ARMv8 support
From: Will Deacon @ 2014-01-29 10:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390935112-28465-1-git-send-email-cov@codeaurora.org>

Hi Christopher,

On Tue, Jan 28, 2014 at 06:51:51PM +0000, Christopher Covington wrote:
> Add the trivial support necessary to get hardware breakpoints
> working for GDB on ARMv8 simulators running in AArch32 mode.
> 
> Acked-by: Will Deacon <will.deacon@arm.com>
> Signed-off-by: Christopher Covington <cov@codeaurora.org>
> ---
> 
>  v3: assume for now that ARMv9 and later will update FSR

Please can you stick this into the patch system? I don't have any other
hw_breakpoint changes queued, so I doubt I'll send a pull for 3.15.

Cheers,

Will

^ permalink raw reply

* [PATCH 11/11] arm: dma-mapping: Add support to extend DMA IOMMU mappings
From: Will Deacon @ 2014-01-29 11:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <52E8DE7D.5020801@samsung.com>

Hi Marek,

On Wed, Jan 29, 2014 at 10:57:01AM +0000, Marek Szyprowski wrote:
> On 2014-01-16 13:44, Andreas Herrmann wrote:
> > Instead of using just one bitmap to keep track of IO virtual addresses
> > (handed out for IOMMU use) introduce a list of iova_ranges (each
> > having its own bitmap). This allows us to extend existing mappings
> > when running out of iova space for a mapping.
> >
> > If there is not enough space in the mapping to service an IO virtual
> > address allocation request, __alloc_iova() tries to extend the mapping
> > -- by allocating another bitmap -- and makes another allocation
> > attempt using the freshly allocated bitmap.
> >
> > This allows arm iommu drivers to start with a decent initial size when
> > an dma_iommu_mapping is created and still to avoid running out of IO
> > virtual addresses for the mapping.
> >
> > Tests were done on Calxeda ECX-2000 with smmu for sata and xgmac.
> > I've used SZ_512K both for initial mapping size and grow_size.
> 
> Thanks for implementing this feature! I remember it was discussed from
> early beginning of arm dma iommu support, but I never had enough time
> to actually implement it. I briefly checked the code and it look fine,
> however I really wonder if we need separate grow_size parameter?
> Personally I would simplify it to simply grow the bitmap by initial
> size until it reaches the maximal size.

That sounds sensible, but I also think it would be worth taking into account
the page sizes supported by the IOMMU as well, since aligning to those makes
sense from a TLB utilisation perspective.

> The whole concept of the simplified bitmap (where 1 bit != 1 page) for
> iova allocation is a specific feature of this code and it has nothing
> to the hardware. After thinking a bit more on the existing
> implementation I've already observed that it is sometimes hard to
> understand the parameters for arm_iommu_create_mapping() function,
> especially the 'order' argument is ofter misunderstood. With your
> patch we got two additional parameters. Maybe it will be much better
> to use only 2 arguments: max_mapping_size and allocation_accuracy.
> The initial bitmap size can be then calculated to fit it into single
> memory page (that's quite important to avoid allocations larger that
> a single memory page). 'allocation_accuracy' will serve the same way
> as 'order' parameter now (but expressed in bytes rather than being
> the multiplier for the number of pages). This way the
> arm_iommu_create_mapping() function should be much easier to
> understand, while keeping the implementation details hidden from the
> caller.

Hmm, I wouldn't guess the SI unit of accuracy to be bytes ;)

Will

^ permalink raw reply

* [PATCH v2 0/5] Add Allwinner A31 SPI controller support
From: Maxime Ripard @ 2014-01-29 11:10 UTC (permalink / raw)
  To: linux-arm-kernel

Hi everyone,

This patchset brings support for the SPI controller found in the
Allwinner A31 SoC.

Even though the controller supports DMA, the driver only supports PIO
mode for now. This driver will be used to bring up and test DMA on the
SoC, so support for the DMA will come eventually.

It doesn't support transfer larger than the FIFO size (128 bytes) for
now, I expect it to be fixed in the future.

Thanks!
Maxime

Changes from v1:
  - Switched to using the transfer_one and set_cs callbacks
  - Switched to using runtime_pm
  - Report an error when we try to do a transfer larger than the FIFO
    size, instead of silently timeouting.
  - Added a Kconfig symbol
  - Move the clock ratio change at transfer time
  - Fixed the PLL6 cell size in the DTSI
  - A few fixes here and there: typos, etc.

Maxime Ripard (5):
  clk: sunxi: Add support for PLL6 on the A31
  ARM: sun6i: dt: Add PLL6 and SPI module clocks
  spi: sunxi: Add Allwinner A31 SPI controller driver
  ARM: sun6i: dt: Add SPI controllers to the A31 DTSI
  ARM: sunxi: Enable A31 SPI and SID in the defconfig

 Documentation/devicetree/bindings/clock/sunxi.txt  |   1 +
 .../devicetree/bindings/spi/spi-sun6i.txt          |  24 ++
 arch/arm/boot/dts/sun6i-a31.dtsi                   |  86 +++-
 arch/arm/configs/sunxi_defconfig                   |   3 +
 drivers/clk/sunxi/clk-sunxi.c                      |  45 ++
 drivers/spi/Kconfig                                |   7 +
 drivers/spi/Makefile                               |   1 +
 drivers/spi/spi-sun6i.c                            | 478 +++++++++++++++++++++
 8 files changed, 636 insertions(+), 9 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-sun6i.txt
 create mode 100644 drivers/spi/spi-sun6i.c

-- 
1.8.4.2

^ permalink raw reply

* [PATCH v2 1/5] clk: sunxi: Add support for PLL6 on the A31
From: Maxime Ripard @ 2014-01-29 11:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390993850-9054-1-git-send-email-maxime.ripard@free-electrons.com>

The A31 has a slightly different PLL6 clock. Add support for this new clock in
our driver.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 Documentation/devicetree/bindings/clock/sunxi.txt |  1 +
 drivers/clk/sunxi/clk-sunxi.c                     | 45 +++++++++++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index c2cb762..954845c 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -11,6 +11,7 @@ Required properties:
 	"allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
 	"allwinner,sun4i-pll5-clk" - for the PLL5 clock
 	"allwinner,sun4i-pll6-clk" - for the PLL6 clock
+	"allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31
 	"allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock
 	"allwinner,sun4i-axi-clk" - for the AXI clock
 	"allwinner,sun4i-axi-gates-clk" - for the AXI gates
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 659e4ea..990ad5d 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -249,7 +249,38 @@ static void sun4i_get_pll5_factors(u32 *freq, u32 parent_rate,
 	*n = DIV_ROUND_UP(div, (*k+1));
 }
 
+/**
+ * sun6i_a31_get_pll6_factors() - calculates n, k factors for A31 PLL6
+ * PLL6 rate is calculated as follows
+ * rate = parent_rate * n * (k + 1) / 2
+ * parent_rate is always 24Mhz
+ */
+
+static void sun6i_a31_get_pll6_factors(u32 *freq, u32 parent_rate,
+				       u8 *n, u8 *k, u8 *m, u8 *p)
+{
+	u8 div;
+
+	/*
+	 * We always have 24MHz / 2, so we can just say that our
+	 * parent clock is 12MHz.
+	 */
+	parent_rate = parent_rate / 2;
+
+	/* Normalize value to a parent_rate multiple (24M / 2) */
+	div = *freq / parent_rate;
+	*freq = parent_rate * div;
+
+	/* we were called to round the frequency, we can now return */
+	if (n == NULL)
+		return;
+
+	*k = div / 32;
+	if (*k > 3)
+		*k = 3;
 
+	*n = DIV_ROUND_UP(div, (*k+1));
+}
 
 /**
  * sun4i_get_apb1_factors() - calculates m, p factors for APB1
@@ -416,6 +447,13 @@ static struct clk_factors_config sun4i_pll5_config = {
 	.kwidth = 2,
 };
 
+static struct clk_factors_config sun6i_a31_pll6_config = {
+	.nshift	= 8,
+	.nwidth = 5,
+	.kshift = 4,
+	.kwidth = 2,
+};
+
 static struct clk_factors_config sun4i_apb1_config = {
 	.mshift = 0,
 	.mwidth = 5,
@@ -457,6 +495,12 @@ static const struct factors_data sun4i_pll5_data __initconst = {
 	.getter = sun4i_get_pll5_factors,
 };
 
+static const struct factors_data sun6i_a31_pll6_data __initconst = {
+	.enable = 31,
+	.table = &sun6i_a31_pll6_config,
+	.getter = sun6i_a31_get_pll6_factors,
+};
+
 static const struct factors_data sun4i_apb1_data __initconst = {
 	.table = &sun4i_apb1_config,
 	.getter = sun4i_get_apb1_factors,
@@ -972,6 +1016,7 @@ free_clkdata:
 static const struct of_device_id clk_factors_match[] __initconst = {
 	{.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,},
 	{.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,},
+	{.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,},
 	{.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,},
 	{.compatible = "allwinner,sun4i-mod0-clk", .data = &sun4i_mod0_data,},
 	{.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,},
-- 
1.8.4.2

^ permalink raw reply related

* [PATCH v2 2/5] ARM: sun6i: dt: Add PLL6 and SPI module clocks
From: Maxime Ripard @ 2014-01-29 11:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390993850-9054-1-git-send-email-maxime.ripard@free-electrons.com>

The module clocks in the A31 are still compatible with the A10 one. Add the SPI
module clocks and the PLL6 in the device tree to allow their use by the SPI
controllers.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun6i-a31.dtsi | 46 ++++++++++++++++++++++++++++++++--------
 1 file changed, 37 insertions(+), 9 deletions(-)

diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
index 5256ad9..0eea325 100644
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -73,16 +73,12 @@
 			clocks = <&osc24M>;
 		};
 
-		/*
-		 * This is a dummy clock, to be used as placeholder on
-		 * other mux clocks when a specific parent clock is not
-		 * yet implemented. It should be dropped when the driver
-		 * is complete.
-		 */
-		pll6: pll6 {
+		pll6: clk at 01c20028 {
 			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <0>;
+			compatible = "allwinner,sun6i-a31-pll6-clk";
+			reg = <0x01c20028 0x4>;
+			clocks = <&osc24M>;
+			clock-output-names = "pll6";
 		};
 
 		cpu: cpu at 01c20050 {
@@ -182,6 +178,38 @@
 					"apb2_uart1", "apb2_uart2", "apb2_uart3",
 					"apb2_uart4", "apb2_uart5";
 		};
+
+		spi0_clk: clk at 01c200a0 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-mod0-clk";
+			reg = <0x01c200a0 0x4>;
+			clocks = <&osc24M>, <&pll6>;
+			clock-output-names = "spi0";
+		};
+
+		spi1_clk: clk at 01c200a4 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-mod0-clk";
+			reg = <0x01c200a4 0x4>;
+			clocks = <&osc24M>, <&pll6>;
+			clock-output-names = "spi1";
+		};
+
+		spi2_clk: clk at 01c200a8 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-mod0-clk";
+			reg = <0x01c200a8 0x4>;
+			clocks = <&osc24M>, <&pll6>;
+			clock-output-names = "spi2";
+		};
+
+		spi3_clk: clk at 01c200ac {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-mod0-clk";
+			reg = <0x01c200ac 0x4>;
+			clocks = <&osc24M>, <&pll6>;
+			clock-output-names = "spi3";
+		};
 	};
 
 	soc at 01c00000 {
-- 
1.8.4.2

^ permalink raw reply related

* [PATCH v2 3/5] spi: sunxi: Add Allwinner A31 SPI controller driver
From: Maxime Ripard @ 2014-01-29 11:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390993850-9054-1-git-send-email-maxime.ripard@free-electrons.com>

The Allwinner A31 has a new SPI controller IP compared to the older Allwinner
SoCs.

It supports DMA, but the driver only does PIO for now, and DMA will be
supported eventually.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 .../devicetree/bindings/spi/spi-sun6i.txt          |  24 ++
 drivers/spi/Kconfig                                |   7 +
 drivers/spi/Makefile                               |   1 +
 drivers/spi/spi-sun6i.c                            | 478 +++++++++++++++++++++
 4 files changed, 510 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-sun6i.txt
 create mode 100644 drivers/spi/spi-sun6i.c

diff --git a/Documentation/devicetree/bindings/spi/spi-sun6i.txt b/Documentation/devicetree/bindings/spi/spi-sun6i.txt
new file mode 100644
index 0000000..21de73d
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-sun6i.txt
@@ -0,0 +1,24 @@
+Allwinner A31 SPI controller
+
+Required properties:
+- compatible: Should be "allwinner,sun6i-a31-spi".
+- reg: Should contain register location and length.
+- interrupts: Should contain interrupt.
+- clocks: phandle to the clocks feeding the SPI controller. Two are
+          needed:
+  - "ahb": the gated AHB parent clock
+  - "mod": the parent module clock
+- clock-names: Must contain the clock names described just above
+- resets: phandle to the reset controller asserting this device in
+          reset
+
+Example:
+
+spi1: spi at 01c69000 {
+	compatible = "allwinner,sun6i-a31-spi";
+	reg = <0x01c69000 0x1000>;
+	interrupts = <0 66 4>;
+	clocks = <&ahb1_gates 21>, <&spi1_clk>;
+	clock-names = "ahb", "mod";
+	resets = <&ahb1_rst 21>;
+};
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index eb1f1ef..004e3b0 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -438,6 +438,13 @@ config SPI_SIRF
 	help
 	  SPI driver for CSR SiRFprimaII SoCs
 
+config SPI_SUN6I
+	tristate "Allwinner A31 SPI controller"
+	depends on ARCH_SUNXI || COMPILE_TEST
+	select PM_RUNTIME
+	help
+	  This enables using the SPI controller on the Allwinner A31 SoCs.
+
 config SPI_MXS
 	tristate "Freescale MXS SPI controller"
 	depends on ARCH_MXS
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index ab8d864..658ec64 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_SPI_SH_HSPI)		+= spi-sh-hspi.o
 obj-$(CONFIG_SPI_SH_MSIOF)		+= spi-sh-msiof.o
 obj-$(CONFIG_SPI_SH_SCI)		+= spi-sh-sci.o
 obj-$(CONFIG_SPI_SIRF)		+= spi-sirf.o
+obj-$(CONFIG_SPI_SUN6I)			+= spi-sun6i.o
 obj-$(CONFIG_SPI_TEGRA114)		+= spi-tegra114.o
 obj-$(CONFIG_SPI_TEGRA20_SFLASH)	+= spi-tegra20-sflash.o
 obj-$(CONFIG_SPI_TEGRA20_SLINK)		+= spi-tegra20-slink.o
diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
new file mode 100644
index 0000000..32f3fc7
--- /dev/null
+++ b/drivers/spi/spi-sun6i.c
@@ -0,0 +1,478 @@
+/*
+ * Copyright (C) 2012 - 2014 Allwinner Tech
+ * Pan Nan <pannan@allwinnertech.com>
+ *
+ * Copyright (C) 2014 Maxime Ripard
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/workqueue.h>
+
+#include <linux/spi/spi.h>
+
+#define SUN6I_FIFO_DEPTH		128
+
+#define SUN6I_GBL_CTL_REG		0x04
+#define SUN6I_GBL_CTL_BUS_ENABLE		BIT(0)
+#define SUN6I_GBL_CTL_MASTER			BIT(1)
+#define SUN6I_GBL_CTL_TP			BIT(7)
+#define SUN6I_GBL_CTL_RST			BIT(31)
+
+#define SUN6I_TFR_CTL_REG		0x08
+#define SUN6I_TFR_CTL_CPHA			BIT(0)
+#define SUN6I_TFR_CTL_CPOL			BIT(1)
+#define SUN6I_TFR_CTL_SPOL			BIT(2)
+#define SUN6I_TFR_CTL_CS_MASK			0x3
+#define SUN6I_TFR_CTL_CS(cs)			(((cs) & SUN6I_TFR_CTL_CS_MASK) << 4)
+#define SUN6I_TFR_CTL_DHB			BIT(8)
+#define SUN6I_TFR_CTL_FBS			BIT(12)
+#define SUN6I_TFR_CTL_XCH			BIT(31)
+
+#define SUN6I_INT_CTL_REG		0x10
+#define SUN6I_INT_CTL_RF_OVF			BIT(8)
+#define SUN6I_INT_CTL_TC			BIT(12)
+
+#define SUN6I_INT_STA_REG		0x14
+
+#define SUN6I_FIFO_CTL_REG		0x18
+#define SUN6I_FIFO_CTL_RF_RST			BIT(15)
+#define SUN6I_FIFO_CTL_TF_RST			BIT(31)
+
+#define SUN6I_FIFO_STA_REG		0x1c
+#define SUN6I_FIFO_STA_RF_CNT_MASK		0x7f
+#define SUN6I_FIFO_STA_RF_CNT_BITS		0
+#define SUN6I_FIFO_STA_TF_CNT_MASK		0x7f
+#define SUN6I_FIFO_STA_TF_CNT_BITS		16
+
+#define SUN6I_CLK_CTL_REG		0x24
+#define SUN6I_CLK_CTL_CDR2_MASK			0xff
+#define SUN6I_CLK_CTL_CDR2(div)			(((div) & SUN6I_CLK_CTL_CDR2_MASK) << 0)
+#define SUN6I_CLK_CTL_CDR1_MASK			0xf
+#define SUN6I_CLK_CTL_CDR1(div)			(((div) & SUN6I_CLK_CTL_CDR1_MASK) << 8)
+#define SUN6I_CLK_CTL_DRS			BIT(12)
+
+#define SUN6I_BURST_CNT_REG		0x30
+#define SUN6I_BURST_CNT(cnt)			((cnt) & 0xffffff)
+
+#define SUN6I_XMIT_CNT_REG		0x34
+#define SUN6I_XMIT_CNT(cnt)			((cnt) & 0xffffff)
+
+#define SUN6I_BURST_CTL_CNT_REG		0x38
+#define SUN6I_BURST_CTL_CNT_STC(cnt)		((cnt) & 0xffffff)
+
+#define SUN6I_TXDATA_REG		0x200
+#define SUN6I_RXDATA_REG		0x300
+
+struct sun6i_spi {
+	struct spi_master	*master;
+	void __iomem		*base_addr;
+	struct clk		*hclk;
+	struct clk		*mclk;
+	struct reset_control	*rstc;
+
+	struct completion	done;
+
+	const u8		*tx_buf;
+	u8			*rx_buf;
+	int			len;
+};
+
+static inline u32 sun6i_spi_read(struct sun6i_spi *sspi, u32 reg)
+{
+	return readl(sspi->base_addr + reg);
+}
+
+static inline void sun6i_spi_write(struct sun6i_spi *sspi, u32 reg, u32 value)
+{
+	writel(value, sspi->base_addr + reg);
+}
+
+static inline void sun6i_spi_drain_fifo(struct sun6i_spi *sspi, int len)
+{
+	u32 reg, cnt;
+	u8 byte;
+
+	/* See how much data is available */
+	reg = sun6i_spi_read(sspi, SUN6I_FIFO_STA_REG);
+	reg &= SUN6I_FIFO_STA_RF_CNT_MASK;
+	cnt = reg >> SUN6I_FIFO_STA_RF_CNT_BITS;
+
+	if (len > cnt)
+		len = cnt;
+
+	while (len--) {
+		byte = readb(sspi->base_addr + SUN6I_RXDATA_REG);
+		if (sspi->rx_buf)
+			*sspi->rx_buf++ = byte;
+	}
+}
+
+static inline void sun6i_spi_fill_fifo(struct sun6i_spi *sspi, int len)
+{
+	u8 byte;
+
+	if (len > sspi->len)
+		len = sspi->len;
+
+	while (len--) {
+		byte = sspi->tx_buf ? *sspi->tx_buf++ : 0;
+		writeb(byte, sspi->base_addr + SUN6I_TXDATA_REG);
+		sspi->len--;
+	}
+}
+
+static void sun6i_spi_set_cs(struct spi_device *spi, bool enable)
+{
+	struct sun6i_spi *sspi = spi_master_get_devdata(spi->master);
+	u32 reg;
+
+	if (!enable)
+		return;
+
+	reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
+	reg &= ~SUN6I_TFR_CTL_CS_MASK;
+	reg |= SUN6I_TFR_CTL_CS(spi->chip_select);
+	sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
+}
+
+
+static int sun6i_spi_transfer_one(struct spi_master *master,
+				  struct spi_device *spi,
+				  struct spi_transfer *tfr)
+{
+	struct sun6i_spi *sspi = spi_master_get_devdata(master);
+	unsigned int mclk_rate, div, timeout;
+	unsigned int tx_len = 0;
+	int ret = 0;
+	u32 reg;
+
+	/* We don't support transfer larger than the FIFO */
+	if (tfr->len > SUN6I_FIFO_DEPTH)
+		return -EINVAL;
+
+	reinit_completion(&sspi->done);
+	sspi->tx_buf = tfr->tx_buf;
+	sspi->rx_buf = tfr->rx_buf;
+	sspi->len = tfr->len;
+
+	/* Clear pending interrupts */
+	sun6i_spi_write(sspi, SUN6I_INT_STA_REG, ~0);
+
+	/* Reset FIFO */
+	sun6i_spi_write(sspi, SUN6I_FIFO_CTL_REG,
+			SUN6I_FIFO_CTL_RF_RST | SUN6I_FIFO_CTL_TF_RST);
+
+	/*
+	 * Setup the transfer control register: Chip Select,
+	 * polarities, etc.
+	 */
+	reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
+
+	if (spi->mode & SPI_CPOL)
+		reg |= SUN6I_TFR_CTL_CPOL;
+	else
+		reg &= ~SUN6I_TFR_CTL_CPOL;
+
+	if (spi->mode & SPI_CPHA)
+		reg |= SUN6I_TFR_CTL_CPHA;
+	else
+		reg &= ~SUN6I_TFR_CTL_CPHA;
+
+	if (spi->mode & SPI_CS_HIGH)
+		reg &= ~SUN6I_TFR_CTL_SPOL;
+	else
+		reg |= SUN6I_TFR_CTL_SPOL;
+
+	if (spi->mode & SPI_LSB_FIRST)
+		reg |= SUN6I_TFR_CTL_FBS;
+	else
+		reg &= ~SUN6I_TFR_CTL_FBS;
+
+	/*
+	 * If it's a TX only transfer, we don't want to fill the RX
+	 * FIFO with bogus data
+	 */
+	if (sspi->rx_buf)
+		reg &= ~SUN6I_TFR_CTL_DHB;
+	else
+		reg |= SUN6I_TFR_CTL_DHB;
+
+	sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
+
+	/* Ensure that we have a parent clock fast enough */
+	mclk_rate = clk_get_rate(sspi->mclk);
+	if (mclk_rate < (2 * spi->max_speed_hz)) {
+		clk_set_rate(sspi->mclk, 2 * spi->max_speed_hz);
+		mclk_rate = clk_get_rate(sspi->mclk);
+	}
+
+	/*
+	 * Setup clock divider.
+	 *
+	 * We have two choices there. Either we can use the clock
+	 * divide rate 1, which is calculated thanks to this formula:
+	 * SPI_CLK = MOD_CLK / (2 ^ cdr)
+	 * Or we can use CDR2, which is calculated with the formula:
+	 * SPI_CLK = MOD_CLK / (2 * (cdr + 1))
+	 * Wether we use the former or the latter is set through the
+	 * DRS bit.
+	 *
+	 * First try CDR2, and if we can't reach the expected
+	 * frequency, fall back to CDR1.
+	 */
+	div = mclk_rate / (2 * spi->max_speed_hz);
+	if (div <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) {
+		if (div > 0)
+			div--;
+
+		reg = SUN6I_CLK_CTL_CDR2(div) | SUN6I_CLK_CTL_DRS;
+	} else {
+		div = ilog2(mclk_rate) - ilog2(spi->max_speed_hz);
+		reg = SUN6I_CLK_CTL_CDR1(div);
+	}
+
+	sun6i_spi_write(sspi, SUN6I_CLK_CTL_REG, reg);
+
+	/* Setup the transfer now... */
+	if (sspi->tx_buf)
+		tx_len = tfr->len;
+
+	/* Setup the counters */
+	sun6i_spi_write(sspi, SUN6I_BURST_CNT_REG, SUN6I_BURST_CNT(tfr->len));
+	sun6i_spi_write(sspi, SUN6I_XMIT_CNT_REG, SUN6I_XMIT_CNT(tx_len));
+	sun6i_spi_write(sspi, SUN6I_BURST_CTL_CNT_REG,
+			SUN6I_BURST_CTL_CNT_STC(tx_len));
+
+	/* Fill the TX FIFO */
+	sun6i_spi_fill_fifo(sspi, SUN6I_FIFO_DEPTH);
+
+	/* Enable the interrupts */
+	sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, SUN6I_INT_CTL_TC);
+
+	/* Start the transfer */
+	reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
+	sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH);
+
+	timeout = wait_for_completion_timeout(&sspi->done,
+					      msecs_to_jiffies(1000));
+	if (!timeout) {
+		ret = -ETIMEDOUT;
+		goto out;
+	}
+
+	sun6i_spi_drain_fifo(sspi, SUN6I_FIFO_DEPTH);
+
+out:
+	sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, 0);
+
+	return ret;
+}
+
+static irqreturn_t sun6i_spi_handler(int irq, void *dev_id)
+{
+	struct sun6i_spi *sspi = dev_id;
+	u32 status = sun6i_spi_read(sspi, SUN6I_INT_STA_REG);
+
+	/* Transfer complete */
+	if (status & SUN6I_INT_CTL_TC) {
+		sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_TC);
+		complete(&sspi->done);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static int sun6i_spi_runtime_resume(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct sun6i_spi *sspi = spi_master_get_devdata(master);
+	int ret;
+
+	ret = clk_prepare_enable(sspi->hclk);
+	if (ret) {
+		dev_err(dev, "Couldn't enable clock 'ahb spi'\n");
+		goto out;
+	}
+
+	ret = clk_prepare_enable(sspi->mclk);
+	if (ret) {
+		dev_err(dev, "Couldn't enable clock 'ahb spi'\n");
+		goto err;
+	}
+
+	ret = reset_control_deassert(sspi->rstc);
+	if (ret) {
+		dev_err(dev, "Couldn't deassert the device from reset\n");
+		goto err2;
+	}
+
+	sun6i_spi_write(sspi, SUN6I_GBL_CTL_REG,
+			SUN6I_GBL_CTL_BUS_ENABLE | SUN6I_GBL_CTL_MASTER | SUN6I_GBL_CTL_TP);
+
+	return 0;
+
+err2:
+	clk_disable_unprepare(sspi->mclk);
+err:
+	clk_disable_unprepare(sspi->hclk);
+out:
+	return ret;
+}
+
+static int sun6i_spi_runtime_suspend(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct sun6i_spi *sspi = spi_master_get_devdata(master);
+
+	reset_control_assert(sspi->rstc);
+	clk_disable_unprepare(sspi->mclk);
+	clk_disable_unprepare(sspi->hclk);
+
+	return 0;
+}
+
+static int sun6i_spi_probe(struct platform_device *pdev)
+{
+	struct spi_master *master;
+	struct sun6i_spi *sspi;
+	struct resource	*res;
+	int ret = 0, irq;
+
+	master = spi_alloc_master(&pdev->dev, sizeof(struct sun6i_spi));
+	if (!master) {
+		dev_err(&pdev->dev, "Unable to allocate SPI Master\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(pdev, master);
+	sspi = spi_master_get_devdata(master);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	sspi->base_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(sspi->base_addr)) {
+		ret = PTR_ERR(sspi->base_addr);
+		goto err;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "No spi IRQ specified\n");
+		ret = -ENXIO;
+		goto err;
+	}
+
+	ret = devm_request_irq(&pdev->dev, irq, sun6i_spi_handler,
+			       0, "sun6i-spi", sspi);
+	if (ret) {
+		dev_err(&pdev->dev, "Cannot request IRQ\n");
+		goto err;
+	}
+
+	sspi->master = master;
+	master->bus_num	= -1;
+	master->set_cs = sun6i_spi_set_cs;
+	master->transfer_one = sun6i_spi_transfer_one;
+	master->num_chipselect = 4;
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
+	master->dev.of_node = pdev->dev.of_node;
+	master->auto_runtime_pm = true;
+
+	/* Setup clocks */
+	sspi->hclk = devm_clk_get(&pdev->dev, "ahb");
+	if (IS_ERR(sspi->hclk)) {
+		dev_err(&pdev->dev, "Unable to acquire AHB clock\n");
+		ret = PTR_ERR(sspi->hclk);
+		goto err;
+	}
+
+	sspi->mclk = devm_clk_get(&pdev->dev, "mod");
+	if (IS_ERR(sspi->mclk)) {
+		dev_err(&pdev->dev, "Unable to acquire module clock\n");
+		ret = PTR_ERR(sspi->mclk);
+		goto err2;
+	}
+
+	init_completion(&sspi->done);
+
+	sspi->rstc = devm_reset_control_get(&pdev->dev, NULL);
+	if (IS_ERR(sspi->rstc)) {
+		dev_err(&pdev->dev, "Couldn't get reset controller\n");
+		ret = PTR_ERR(sspi->rstc);
+		goto err3;
+	}
+
+	pm_runtime_enable(&pdev->dev);
+
+	ret = spi_register_master(master);
+	if (ret) {
+		dev_err(&pdev->dev, "cannot register SPI master\n");
+		goto err4;
+	}
+
+	return 0;
+
+err4:
+	pm_runtime_disable(&pdev->dev);
+err3:
+	clk_disable_unprepare(sspi->mclk);
+err2:
+	clk_disable_unprepare(sspi->hclk);
+err:
+	spi_master_put(master);
+
+	return ret;
+}
+
+static int sun6i_spi_remove(struct platform_device *pdev)
+{
+	struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
+
+	spi_unregister_master(master);
+	pm_runtime_disable(&pdev->dev);
+	spi_master_put(master);
+
+	return 0;
+}
+
+static const struct of_device_id sun6i_spi_match[] = {
+	{ .compatible = "allwinner,sun6i-a31-spi", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, sun6i_spi_match);
+
+static const struct dev_pm_ops sun6i_spi_pm_ops = {
+	.runtime_resume		= sun6i_spi_runtime_resume,
+	.runtime_suspend	= sun6i_spi_runtime_suspend,
+};
+
+static struct platform_driver sun6i_spi_driver = {
+	.probe	= sun6i_spi_probe,
+	.remove	= sun6i_spi_remove,
+	.driver	= {
+		.name		= "sun6i-spi",
+		.owner		= THIS_MODULE,
+		.of_match_table	= sun6i_spi_match,
+		.pm		= &sun6i_spi_pm_ops,
+	},
+};
+module_platform_driver(sun6i_spi_driver);
+
+MODULE_AUTHOR("Pan Nan <pannan@allwinnertech.com>");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_DESCRIPTION("Allwinner A31 SPI controller driver");
+MODULE_LICENSE("GPL");
-- 
1.8.4.2

^ permalink raw reply related

* [PATCH v2 4/5] ARM: sun6i: dt: Add SPI controllers to the A31 DTSI
From: Maxime Ripard @ 2014-01-29 11:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390993850-9054-1-git-send-email-maxime.ripard@free-electrons.com>

The A31 has 4 SPI controllers. Add them in the DTSI.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun6i-a31.dtsi | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
index 0eea325..57af66f 100644
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -340,6 +340,46 @@
 			status = "disabled";
 		};
 
+		spi0: spi at 01c68000 {
+			compatible = "allwinner,sun6i-a31-spi";
+			reg = <0x01c68000 0x1000>;
+			interrupts = <0 65 4>;
+			clocks = <&ahb1_gates 20>, <&spi0_clk>;
+			clock-names = "ahb", "mod";
+			resets = <&ahb1_rst 20>;
+			status = "disabled";
+		};
+
+		spi1: spi at 01c69000 {
+			compatible = "allwinner,sun6i-a31-spi";
+			reg = <0x01c69000 0x1000>;
+			interrupts = <0 66 4>;
+			clocks = <&ahb1_gates 21>, <&spi1_clk>;
+			clock-names = "ahb", "mod";
+			resets = <&ahb1_rst 21>;
+			status = "disabled";
+		};
+
+		spi2: spi at 01c6a000 {
+			compatible = "allwinner,sun6i-a31-spi";
+			reg = <0x01c6a000 0x1000>;
+			interrupts = <0 67 4>;
+			clocks = <&ahb1_gates 22>, <&spi2_clk>;
+			clock-names = "ahb", "mod";
+			resets = <&ahb1_rst 22>;
+			status = "disabled";
+		};
+
+		spi3: spi at 01c6b000 {
+			compatible = "allwinner,sun6i-a31-spi";
+			reg = <0x01c6b000 0x1000>;
+			interrupts = <0 68 4>;
+			clocks = <&ahb1_gates 23>, <&spi3_clk>;
+			clock-names = "ahb", "mod";
+			resets = <&ahb1_rst 23>;
+			status = "disabled";
+		};
+
 		gic: interrupt-controller at 01c81000 {
 			compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic";
 			reg = <0x01c81000 0x1000>,
-- 
1.8.4.2

^ permalink raw reply related

* [PATCH v2 5/5] ARM: sunxi: Enable A31 SPI and SID in the defconfig
From: Maxime Ripard @ 2014-01-29 11:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390993850-9054-1-git-send-email-maxime.ripard@free-electrons.com>

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/configs/sunxi_defconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig
index 3e2259b..b5df4a5 100644
--- a/arch/arm/configs/sunxi_defconfig
+++ b/arch/arm/configs/sunxi_defconfig
@@ -24,6 +24,7 @@ CONFIG_IP_PNP_BOOTP=y
 # CONFIG_WIRELESS is not set
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_EEPROM_SUNXI_SID=y
 CONFIG_NETDEVICES=y
 CONFIG_SUN4I_EMAC=y
 # CONFIG_NET_CADENCE is not set
@@ -48,6 +49,8 @@ CONFIG_I2C=y
 # CONFIG_I2C_COMPAT is not set
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MV64XXX=y
+CONFIG_SPI=y
+CONFIG_SPI_SUN6I=y
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
-- 
1.8.4.2

^ permalink raw reply related

* imx-drm: screen flickering
From: Sascha Hauer @ 2014-01-29 11:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAH9NwWe673znThNPWRvOCyAU2o7M-oouHD7+1tyRcmWTeJ8YFw@mail.gmail.com>

Hi Christian,

On Tue, Jan 28, 2014 at 09:11:32AM +0100, Christian Gmeiner wrote:
> Hi all.
> 
> From time to time it happens that my LVDS display is flickering (look
> at scroll bar in the video).
> https://drive.google.com/file/d/0B_fznDimUHVubWtvVFlMTkdBbUU/edit?usp=sharing
> 
> I really want to find the root cause of it, but I do not know where to
> start. I can trigger this
> sometimes after xscreensever "blanks" the screen and the screensafer
> gets disabled
> via user input.
> 
> Any hints?

Sorry, no idea. Philipp and me watched the video, but we both haven't
seen something like this before.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply

* [PATCH v2 1/2] ARM: dts: imx6sl-evk: Add PFUZE100 support
From: Fabio Estevam @ 2014-01-29 11:58 UTC (permalink / raw)
  To: linux-arm-kernel

From: Fabio Estevam <fabio.estevam@freescale.com>

imx6sl-evk board has Freescale PFUZE100 regulator, so add support for it.

Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
---
Changes since v1:
- Remove pingrp

 arch/arm/boot/dts/imx6sl-evk.dts | 113 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 113 insertions(+)

diff --git a/arch/arm/boot/dts/imx6sl-evk.dts b/arch/arm/boot/dts/imx6sl-evk.dts
index 0001804..4fc62e8 100644
--- a/arch/arm/boot/dts/imx6sl-evk.dts
+++ b/arch/arm/boot/dts/imx6sl-evk.dts
@@ -46,6 +46,112 @@
 	};
 };
 
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	pmic: pfuze100 at 08 {
+		compatible = "fsl,pfuze100";
+		reg = <0x08>;
+
+		regulators {
+			sw1a_reg: sw1ab {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw1c_reg: sw1c {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw2_reg: sw2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3a_reg: sw3a {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3b_reg: sw3b {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw4_reg: sw4 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			swbst_reg: swbst {
+				regulator-min-microvolt = <5000000>;
+				regulator-max-microvolt = <5150000>;
+			};
+
+			snvs_reg: vsnvs {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vref_reg: vrefddr {
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vgen1_reg: vgen1 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen2_reg: vgen2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen3_reg: vgen3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			vgen4_reg: vgen4 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen5_reg: vgen5 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen6_reg: vgen6 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
 &ecspi1 {
 	fsl,spi-num-chipselects = <1>;
 	cs-gpios = <&gpio4 11 0>;
@@ -86,6 +192,13 @@
 			>;
 		};
 
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX6SL_PAD_I2C1_SCL__I2C1_SCL	0x4001b8b1
+				MX6SL_PAD_I2C1_SDA__I2C1_SDA	0x4001b8b1
+			>;
+		};
+
 		pinctrl_ecspi1: ecspi1grp {
 			fsl,pins = <
 				MX6SL_PAD_ECSPI1_MISO__ECSPI1_MISO	0x100b1
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH v2 2/2] ARM: dts: imx6sl-evk: Add audio support
From: Fabio Estevam @ 2014-01-29 11:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390996695-25164-1-git-send-email-festevam@gmail.com>

From: Fabio Estevam <fabio.estevam@freescale.com>

imx6sl-evk has a wm8962 codec. Add support for it.

Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
---
Changes since v1:
- Remove pingrp
- Use regulator at num mode

 arch/arm/boot/dts/imx6sl-evk.dts | 81 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)

diff --git a/arch/arm/boot/dts/imx6sl-evk.dts b/arch/arm/boot/dts/imx6sl-evk.dts
index 4fc62e8..17db01a 100644
--- a/arch/arm/boot/dts/imx6sl-evk.dts
+++ b/arch/arm/boot/dts/imx6sl-evk.dts
@@ -43,9 +43,47 @@
 			gpio = <&gpio4 2 0>;
 			enable-active-high;
 		};
+
+		reg_aud3v: regulator at 2 {
+			compatible = "regulator-fixed";
+			regulator-name = "wm8962-supply-3v15";
+			regulator-min-microvolt = <3150000>;
+			regulator-max-microvolt = <3150000>;
+			regulator-boot-on;
+		};
+
+		reg_aud4v: regulator at 3 {
+			compatible = "regulator-fixed";
+			regulator-name = "wm8962-supply-4v2";
+			regulator-min-microvolt = <4325000>;
+			regulator-max-microvolt = <4325000>;
+			regulator-boot-on;
+		};
+	};
+
+	sound {
+		compatible = "fsl,imx6sl-evk-wm8962", "fsl,imx-audio-wm8962";
+		model = "wm8962-audio";
+		ssi-controller = <&ssi2>;
+		audio-codec = <&codec>;
+		audio-routing =
+			"Headphone Jack", "HPOUTL",
+			"Headphone Jack", "HPOUTR",
+			"Ext Spk", "SPKOUTL",
+			"Ext Spk", "SPKOUTR",
+			"AMIC", "MICBIAS",
+			"IN3R", "AMIC";
+		mux-int-port = <2>;
+		mux-ext-port = <3>;
 	};
 };
 
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux3>;
+	status = "okay";
+};
+
 &i2c1 {
 	clock-frequency = <100000>;
 	pinctrl-names = "default";
@@ -152,6 +190,27 @@
 	};
 };
 
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	codec: wm8962 at 1a {
+		compatible = "wlf,wm8962";
+		reg = <0x1a>;
+		clocks = <&clks IMX6SL_CLK_EXTERN_AUDIO>;
+		DCVDD-supply = <&vgen3_reg>;
+		DBVDD-supply = <&reg_aud3v>;
+		AVDD-supply = <&vgen3_reg>;
+		CPVDD-supply = <&vgen3_reg>;
+		MICVDD-supply = <&reg_aud3v>;
+		PLLVDD-supply = <&vgen3_reg>;
+		SPKVDD1-supply = <&reg_aud4v>;
+		SPKVDD2-supply = <&reg_aud4v>;
+	};
+};
+
 &ecspi1 {
 	fsl,spi-num-chipselects = <1>;
 	cs-gpios = <&gpio4 11 0>;
@@ -189,6 +248,16 @@
 				MX6SL_PAD_REF_CLK_32K__GPIO3_IO22 0x17059
 				MX6SL_PAD_KEY_COL4__GPIO4_IO00	0x80000000
 				MX6SL_PAD_KEY_COL5__GPIO4_IO02	0x80000000
+				MX6SL_PAD_AUD_MCLK__AUDIO_CLK_OUT 0x4130b0
+			>;
+		};
+
+		pinctrl_audmux3: audmux3grp {
+			fsl,pins = <
+				MX6SL_PAD_AUD_RXD__AUD3_RXD	  0x4130b0
+				MX6SL_PAD_AUD_TXC__AUD3_TXC	  0x4130b0
+				MX6SL_PAD_AUD_TXD__AUD3_TXD	  0x4110b0
+				MX6SL_PAD_AUD_TXFS__AUD3_TXFS	  0x4130b0
 			>;
 		};
 
@@ -199,6 +268,13 @@
 			>;
 		};
 
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX6SL_PAD_I2C2_SCL__I2C2_SCL	0x4001b8b1
+				MX6SL_PAD_I2C2_SDA__I2C2_SDA	0x4001b8b1
+			>;
+		};
+
 		pinctrl_ecspi1: ecspi1grp {
 			fsl,pins = <
 				MX6SL_PAD_ECSPI1_MISO__ECSPI1_MISO	0x100b1
@@ -374,6 +450,11 @@
 	status = "okay";
 };
 
+&ssi2 {
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
 &uart1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_uart1>;
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH v2] ARM: dts: imx6qdl-sabreauto: Add PFUZE100 support
From: Fabio Estevam @ 2014-01-29 12:15 UTC (permalink / raw)
  To: linux-arm-kernel

From: Fabio Estevam <fabio.estevam@freescale.com>

mx6 sabreauto boards have Freescale PFUZE100 regulator, so add support for it.

Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
---
Changes since v1:
- Remove pingrp

 arch/arm/boot/dts/imx6qdl-sabreauto.dtsi | 113 +++++++++++++++++++++++++++++++
 1 file changed, 113 insertions(+)

diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
index 10a00e4..772c5a1 100644
--- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
@@ -63,6 +63,112 @@
 	status = "okay";
 };
 
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	pmic: pfuze100 at 08 {
+		compatible = "fsl,pfuze100";
+		reg = <0x08>;
+
+		regulators {
+			sw1a_reg: sw1ab {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw1c_reg: sw1c {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw2_reg: sw2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3a_reg: sw3a {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3b_reg: sw3b {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw4_reg: sw4 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			swbst_reg: swbst {
+				regulator-min-microvolt = <5000000>;
+				regulator-max-microvolt = <5150000>;
+			};
+
+			snvs_reg: vsnvs {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vref_reg: vrefddr {
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vgen1_reg: vgen1 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen2_reg: vgen2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen3_reg: vgen3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			vgen4_reg: vgen4 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen5_reg: vgen5 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen6_reg: vgen6 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
 &iomuxc {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_hog>;
@@ -111,6 +217,13 @@
 			>;
 		};
 
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_EB2__I2C2_SCL	0x4001b8b1
+				MX6QDL_PAD_KEY_ROW3__I2C2_SDA	0x4001b8b1
+			>;
+		};
+
 		pinctrl_gpmi_nand: gpminandgrp {
 			fsl,pins = <
 				MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH] ARM: sa1100: fix compile problem on Collie
From: Linus Walleij @ 2014-01-29 12:23 UTC (permalink / raw)
  To: linux-arm-kernel

Due to a problem in the MFD Kconfig it was not possible to
compile the UCB battery driver for the Collie SA1100 system,
in turn making it impossible to compile in the battery driver.
(See patch "mfd: include all drivers in subsystem menu".)

After fixing the MFD Kconfig (separate patch) a compile error
appears in the Collie battery driver due to the <mach/collie.h>
implicitly requiring <mach/hardware.h> through <linux/gpio.h>
via <mach/gpio.h> prior to commit
40ca061b "ARM: 7841/1: sa1100: remove complex GPIO interface".

Fix this up by including the required header into
<mach/collie.h>.

Cc: stable at vger.kernel.org
Cc: Andrea Adami <andrea.adami@gmail.com>
Cc: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/mach-sa1100/include/mach/collie.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/mach-sa1100/include/mach/collie.h b/arch/arm/mach-sa1100/include/mach/collie.h
index f33679d2d3ee..50e1d850ee2e 100644
--- a/arch/arm/mach-sa1100/include/mach/collie.h
+++ b/arch/arm/mach-sa1100/include/mach/collie.h
@@ -13,6 +13,8 @@
 #ifndef __ASM_ARCH_COLLIE_H
 #define __ASM_ARCH_COLLIE_H
 
+#include "hardware.h" /* Gives GPIO_MAX */
+
 extern void locomolcd_power(int on);
 
 #define COLLIE_SCOOP_GPIO_BASE	(GPIO_MAX + 1)
-- 
1.8.5.3

^ permalink raw reply related

* [PATCH v2 3/5] spi: sunxi: Add Allwinner A31 SPI controller driver
From: Mark Brown @ 2014-01-29 12:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390993850-9054-4-git-send-email-maxime.ripard@free-electrons.com>

On Wed, Jan 29, 2014 at 12:10:48PM +0100, Maxime Ripard wrote:

> +config SPI_SUN6I
> +	tristate "Allwinner A31 SPI controller"
> +	depends on ARCH_SUNXI || COMPILE_TEST
> +	select PM_RUNTIME
> +	help
> +	  This enables using the SPI controller on the Allwinner A31 SoCs.
> +

A select of PM_RUNTIME is both surprising and odd - why is that there?
The usual idiom is that the device starts out powered up (flagged using
pm_runtime_set_active()) and then runtime PM then suspends it when it's
compiled in.  That way if for some reason people want to avoid runtime
PM they can still use the device.

> +static void sun6i_spi_set_cs(struct spi_device *spi, bool enable)
> +{
> +	struct sun6i_spi *sspi = spi_master_get_devdata(spi->master);
> +	u32 reg;
> +
> +	if (!enable)
> +		return;
> +
> +	reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
> +	reg &= ~SUN6I_TFR_CTL_CS_MASK;
> +	reg |= SUN6I_TFR_CTL_CS(spi->chip_select);
> +	sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
> +}

The !enable means that it'll only ever be able to go one way.  Also note
that the documentation was clarified here to make the enable flag be the
absolute logic level, not if chip select was asserted.

> +	timeout = wait_for_completion_timeout(&sspi->done,
> +					      msecs_to_jiffies(1000));
> +	if (!timeout) {
> +		ret = -ETIMEDOUT;
> +		goto out;
> +	}
> +
> +	sun6i_spi_drain_fifo(sspi, SUN6I_FIFO_DEPTH);

This means we can only transfer a single FIFO of data?  I didn't see a
check on the transfer length.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140129/34ca1e5b/attachment.sig>

^ permalink raw reply

* [PATCH] arm: Add Arm Erratum 773769 for Large data RAM latency.
From: Sander @ 2014-01-29 12:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAD=FV=XqoSGpQ_Yrjj4hvV_0FSMfQGcGEsKkL1Stnm9m5s2Xvw@mail.gmail.com>

Doug Anderson wrote (ao):
> On Wed, Jan 8, 2014 at 1:08 PM, Nicolas Pitre <nico@fluxnic.net> wrote:
> > On Wed, 8 Jan 2014, Doug Anderson wrote:
> >> * If Joe Upstream wants to run an upstream kernel on some type of
> >> exynos5250 product (Samsung ARM Chromebook, HP Chromebook 11, Nexus 10
> >> are the ones I know of) then he will deal with the small number of
> >> crashes or figure out a solution.
> >
> > If Joe Upstream wants to run an upstream kernel, doesn't he have to
> > unscrew his write protect switch first, at which point the RO firmware
> > can be updated as well?
> 
> Actually, no.  You can move your device into dev mode and run any
> kernel you want.  You'll get an annoying "you're in dev mode" screen
> at every bootup, but otherwise it works just fine.
> 
> Going into dev mode requires some special keystrokes at bootup and a
> wipe of your hard disk but no screwdrivers.

And there is http://www.arndaleboard.org/ where you just put an upstream
kernel on sd and boot.

	Sander

^ permalink raw reply

* [PATCH RFC v2 2/2] Documentation: arm: define DT C-states bindings
From: Lorenzo Pieralisi @ 2014-01-29 12:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140127155924.GA2178@e103592.cambridge.arm.com>

On Mon, Jan 27, 2014 at 03:59:37PM +0000, Dave Martin wrote:
> On Fri, Jan 24, 2014 at 05:58:07PM +0000, Lorenzo Pieralisi wrote:

[...]

> > > > state0 {
> > > >         index = <2>;
> > > >         compatible = "arm,cpu-power-state";
> > > >         latency = <...>;
> > > >         /*
> > > >          * This means that when the state is entered, the power
> > > >          * controller should use register index 0 and state 0,
> > > >          * whose meaning is power controller specific. Since we
> > > >          * know all components affected (for every component
> > > >          * we declare its power domain(s) and states so we
> > > >          * know what components are affected by the state entry.
> > > >          * Given the cache node above and this phandle, the state
> > > >          * implies that the cache is retained, register index == 0 state == 0
> > > >          /*
> > > >         power-domain =<&foo_power_controller 0 0>;
> > > 
> > > for retention state we need to set the power domain in state 1
> > >         power-domain =<&foo_power_controller 0 1>;
> 
> The name "power-domain" probably needs changing if the specifier contains
> state information too.
> 
> Instead, we could call it "power-state" or similar.
> 
> 
> Key issues I see:
> 
> 1) How to describe platforms where there is no "power controller" as such,
>    just a bunch of clocks and regulators that Linux has to poke directly.
> 
> 2) Two devices might have the same power controller (in terms of IP and
>    revision), but integrated in different ways.  So, maybe thinking of
>    the referenced thing as a power controller is not correct.  We can
>    thing in terms of referring to individual power domains, or maybe
>    to a "power model" for the SoC.

The example was misleading. There is no link to a power controller as
such, the phandle is to a power domain, which fits with what you are
saying, basically the C-state does not care about how the power domain
is implemented, it just defines that that specific power domain is
affected. I am not sure we should change the naming either, a C-state
defines a power-domain specifier, which implies a certain behaviour
for a power domain. It is platform specific, so for certain platforms
the cells represent a state for others they do not.

>    The power domain or model becomes a container for power (domains and)
>    states, and refers to the IP blocks (power controllers, regulators,
>    clocks, clamps, whatever) required to implement it.
> 
>    This change of abstraction might map more naturally onto "bunch
>    of clocks and regulators" situations: the power model or domain
>    binding can make symbolic references to clocks and regulators etc.,
>    so that the binding becomes less dependent on the exact content of
>    the rest of the DT.

Exactly, I agree, the complexity is in the power-domain (how states are
handled, what components should be programmed, etc) the C-state just
defines what power-domain it affects, with power domain specifier cells
providing additional, power domain specific, semantics (ie retention vs.
shutdown).

> 3) We need to be very clear that the power state specifier needs to be
>    defined in terms of the actual hardware effects in the relevant SoC-
>    specific binding -- at the "what" level, rather than "how".
> 
>    There's a fair chance of people getting lazy: they'll just stuff
>    indices in the DT which map to random LUTs in the Linux driver.  In
>    that case, the DT would be describing the Linux driver, not the
>    hardware -- that's not what we want.
> 
>    Delegating the job of defining power states to the SoC documentation
>    seems acceptable, though.

I agree, and I think we are pretty close to a general agreement on this
specific subject.

Thank you,
Lorenzo

^ permalink raw reply


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