Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [RFC/PATCH 3/7] ARM: ARM11 MPCore: {clean,flush}_pmd_entry are not preempt safe
From: Catalin Marinas @ 2011-10-11  9:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317955121-28047-4-git-send-email-gdavis@mvista.com>

On Fri, Oct 07, 2011 at 03:38:37AM +0100, gdavis at mvista.com wrote:
> diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
> index 594d677..3c8253f 100644
> --- a/arch/arm/mm/mmu.c
> +++ b/arch/arm/mm/mmu.c
> @@ -567,12 +567,24 @@ static void __init alloc_init_section(pud_t *pud, unsigned long addr,
>  		if (addr & SECTION_SIZE)
>  			pmd++;
>  
> +		if (cache_ops_need_broadcast())
> +			preempt_disable();
>  		do {
>  			*pmd = __pmd(phys | type->prot_sect);
>  			phys += SECTION_SIZE;
>  		} while (pmd++, addr += SECTION_SIZE, addr != end);
>  
> +		/* FIXME: Multiple PMD entries may be written above
> +		 * but only one cache line, up to 8 PMDs depending
> +		 * on the alignment of this mapping, is flushed below.
> +		 * IFF this mapping spans >8MiB, then only the first
> +		 * 8MiB worth of entries will be flushed.  Entries
> +		 * above the 8MiB limit will not be flushed if I
> +		 * read this correctly.
> +		 */
>  		flush_pmd_entry(p);
> +		if (cache_ops_need_broadcast())
> +			preempt_enable();

My reading of the create_mapping() code is that alloc_init_pud() and
alloc_init_section() are called with a 2MB range only (that's 2
entries) given by pgd_addr_end().

-- 
Catalin

^ permalink raw reply

* [RFC/PATCH 5/7] ARM: Move get_thread_info macro definition to <asm/assembler.h>
From: Catalin Marinas @ 2011-10-11  9:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317955121-28047-6-git-send-email-gdavis@mvista.com>

On Fri, Oct 07, 2011 at 03:38:39AM +0100, gdavis at mvista.com wrote:
> diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
> index 29035e8..78397d0 100644
> --- a/arch/arm/include/asm/assembler.h
> +++ b/arch/arm/include/asm/assembler.h
> @@ -23,6 +23,19 @@
>  #include <asm/ptrace.h>
>  #include <asm/domain.h>
>  
> +#ifndef CONFIG_THUMB2_KERNEL
> +	.macro	get_thread_info, rd
> +	mov	\rd, sp, lsr #13
> +	mov	\rd, \rd, lsl #13
> +	.endm
> +#else   /* CONFIG_THUMB2_KERNEL */
> +	.macro	get_thread_info, rd
> +	mov	\rd, sp
> +	lsr	\rd, \rd, #13
> +	mov	\rd, \rd, lsl #13
> +	.endm
> +#endif  /* !CONFIG_THUMB2_KERNEL */

We could even write some preempt_enable and preempt_disable asm macros,
I think it would simplify the code in the other files.

-- 
Catalin

^ permalink raw reply

* sched: ARM: arch_scale_freq_power
From: Peter Zijlstra @ 2011-10-11 10:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAP245DXbj5nEB2ya5BWVYinvr2RQ+m7vmuHHT3fD1iVZZQ2C5g@mail.gmail.com>

On Tue, 2011-10-11 at 15:08 +0530, Amit Kucheria wrote:

> > That shouldn't be done using cpu_power, we have sched_smt_power_savings
> > and sched_mc_power_savings for stuff like that.
> 
> AFAICT, sched_mc assume all cores to have the same capacity - which is
> certainly true of the x86 architecture. But in ARM you can see hybrid
> cores[1] designed using different fab technology, so that some cores
> can run at 'n' GHz and some at 'm' GHz. The idea being that when there
> isn't much to do (e.g periodic keep alives for messaging, email, etc.)
> you don't wake up the higher power-consuming cores.
> 
> From TFA[1],  "Sheeva was already capable of 1.2GHz, but the new
> design can go up to 1.5GHz. But only two of the 628's Sheeva cores run
> at the full 1.5GHz. The third one is down-clocked to 624MHz, and
> interesting design choice that saves on power but adds some extra
> utility. In a sense, the 628 could be called a 2.5-core design."

Cute :-)

> Are we mistaken in thinking that sched_mc can not currently handle
> this usecase? How would we 'tune' sched_mc to do this w/o playing with
> cpu_power?

Yeah, sched_mc wants some TLC there.

> > Although I would really like to kill all those different
> > sched_*_power_savings knobs and reduce it to one.
> >
> >> If the cpu_power is
> >> higher than 1024, the cpu is no more seen out of capacity by the
> >> load_balance as soon as a short process is running and teh main result
> >> is that the small tasks will stay on the same cpu. This configuration
> >> is mainly usefull for ARM dual core system when we want to power gate
> >> one cpu. I use cyclictest to simulate such use case.
> >
> > Yeah, but that's wrong.
> 
> What is wrong - the use case simulation using cyclictest? Can you
> suggest better tools?

Using cpu_power to do power saving load-balancing like that.

So ideally cpu_power is simply a factor in the weight balance decision
such that:

	cpu_weight_i      cpu_weigjt_j
	------------  ~=  ------------
	cpu_power_i       cpu_power_j

This yields that under sufficient[*] load, eg. 5 equal weight tasks and
your 2.5 core thingy, you'd get 2:2:1

The decision on what to do on under-utilized systems should be separate
from this.

Currently the load-balancer doesn't know about 'short' running processes
at all, we just have nr_running and weight it doesn't know/care about
for how long those will be around for.

Now for some of the cgroup crap we track a time-weighted weight average,
and pjt was talking about pulling that up into the normal code to get
rid of our multitude of different ways to calculate actual load. [**]

(/me pokes pjt with a sharp stick, where those patches at!?)

But that only gets you half-way there, you also need to compute an
effective time-weighted load per task to go with that.. now while all
that is quite feasible, the problem is overhead. We very much already
are way to expensive and should be cutting back, not keep adding more
and more accounting.

[*] Sufficient such that the weight problem is feasible. eg. 3 equal
tasks on 2 equal cores can never be statically balanced, 2 unequal tasks
on 2 equal cores (or v.v.) can't ever be balanced.

[**] I suspect this might solve the over-balancing problem triggered by
tasks woken from the tick that also does the load-balance pass. This
load-balance pass will run in sIRQ context and thus preempt running all
those just woken tasks, thus giving the impression the CPU is very busy,
while in fact most those tasks will instantly go back to sleep after
finding nothing to do.

^ permalink raw reply

* [PATCH v3 1/6] iommu/core: split mapping to page sizes as supported by the hardware
From: Roedel, Joerg @ 2011-10-11 10:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAK=WgbYR_qx53Z7s3R=q29KYo8ebYCH9H9=2OrrWXWMv6=-iOQ@mail.gmail.com>

Hi Ohad,

On Mon, Oct 10, 2011 at 01:02:46PM -0400, Ohad Ben-Cohen wrote:
> On Mon, Oct 10, 2011 at 5:36 PM, Roedel, Joerg <Joerg.Roedel@amd.com> wrote:
> > Yes, somthing like that. Probably the iommu_ops->unmap function should
> > be turned into a unmap_page function call which only takes an iova and
> > no size parameter. The iommu-driver unmaps the page pointing to that
> > iova and returns the size of the page unmapped. This still allows the
> > simple implementation for the unmap-call.
> 
> Yes, exactly. It will take some time to migrate all drivers (today we
> have 4 drivers, each of which is implementing a slightly different
> ->unmap() semantics), but at least let's not accept any new driver
> that doesn't adhere to this, otherwise it's going to be even harder
> for the API to evolve.

Agreed. We should change the existing drivers one-by-one.

> > We don't need to really enforce the calls to be symetric. But we can
> > define that we only give the guarantee about what will be unmapped
> > when the calls are symetric.
> 
> Sounds good to me. I'll add this to the kernel doc patch (which I'll
> submit after this patch set materializes), and when/if we move to
> symmetric only, we will update it.

Great. So if no one disagrees with this direction (this means all the
other people on Cc :) ) it is the way to.

	Joerg

-- 
AMD Operating System Research Center

Advanced Micro Devices GmbH Einsteinring 24 85609 Dornach
General Managers: Alberto Bozzo, Andrew Bowd
Registration: Dornach, Landkr. Muenchen; Registerger. Muenchen, HRB Nr. 43632

^ permalink raw reply

* [PATCH v3 1/6] iommu/core: split mapping to page sizes as supported by the hardware
From: Roedel, Joerg @ 2011-10-11 10:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAK=WgbbXpqfrYYU4Or_q_ZtYzF9dH41hT+zXhB9-4pKjYFjK8w@mail.gmail.com>

On Mon, Oct 10, 2011 at 06:01:06PM -0400, Ohad Ben-Cohen wrote:
> > On Mon, Oct 10, 2011 at 5:36 PM, Roedel, Joerg <Joerg.Roedel@amd.com> wrote:
> >> The master branch is best to base your patches on for generic work.
> 
> It looks like the master branch is missing something like this:
> 
> >From acb316aa4bcaf383e8cb1580e30c8635e0a34369 Mon Sep 17 00:00:00 2001
> From: Ohad Ben-Cohen <ohad@wizery.com>
> Date: Mon, 10 Oct 2011 23:55:51 +0200
> Subject: [PATCH] iommu/core: fix build issue
> 
> Fix this:
> 
> drivers/iommu/iommu.c: In function 'iommu_commit':
> drivers/iommu/iommu.c:291: error: 'iommu_ops' undeclared (first use in
> this function)
> 
> Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
> ---
>  drivers/iommu/iommu.c |    4 ++--
>  1 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
> index 909b0d2..a5131f1 100644
> --- a/drivers/iommu/iommu.c
> +++ b/drivers/iommu/iommu.c
> @@ -288,7 +288,7 @@ EXPORT_SYMBOL_GPL(iommu_unmap);
> 
>  void iommu_commit(struct iommu_domain *domain)
>  {
> -	if (iommu_ops->commit)
> -		iommu_ops->commit(domain);
> +	if (domain->ops->commit)
> +		domain->ops->commit(domain);
>  }
>  EXPORT_SYMBOL_GPL(iommu_commit);
> -- 
> 1.7.4.1

Whoops. This iommu_commit branch wasn't meant to be in master already.
I'll try to fix that.

	Joerg

-- 
AMD Operating System Research Center

Advanced Micro Devices GmbH Einsteinring 24 85609 Dornach
General Managers: Alberto Bozzo, Andrew Bowd
Registration: Dornach, Landkr. Muenchen; Registerger. Muenchen, HRB Nr. 43632

^ permalink raw reply

* sched: ARM: arch_scale_freq_power
From: Peter Zijlstra @ 2011-10-11 10:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAKfTPtDzY4pORvWd3Qa6kqpNsspKN7iEskQ+7F5D=mAwQWoKNg@mail.gmail.com>

On Tue, 2011-10-11 at 11:40 +0200, Vincent Guittot wrote:
> On 11 October 2011 11:13, Peter Zijlstra <a.p.zijlstra@chello.nl> wrote:
> > On Tue, 2011-10-11 at 10:51 +0200, Vincent Guittot wrote:
> >> I have several goals. The 1st one is that I need to put more load on
> >> some cpus when I have packages with different cpu frequency.
> >
> > That should be rather easy.
> >
> 
> I agree, I was mainly wondering If I should use a [1-1024] or a
> [1024-xxxx] range and it seems that both can be used according : SMT
> uses <1024 and x86 turbo mode uses >1024

Well, turbo mode would typically only boost a cpu 25% or so, and only
while idling other cores to keep under its thermal limit. So its not
sufficient to actually affect the capacity calculation much if at all.

> >> Then, I have some use cases which have several running tasks but a low
> >> cpu load. In this case, the small tasks are spread on several cpu by
> >> the load_balance whereas they could be easily handled by one cpu
> >> without significant performance modification.
> >
> > That shouldn't be done using cpu_power, we have sched_smt_power_savings
> > and sched_mc_power_savings for stuff like that.
> >
> 
> sched_mc_power_saving works fine when we have more than 2 cpus but
> can't apply on a dual core because it needs at least 2 sched_groups
> and the nr_running of these sched_groups must be higher than 0 but
> smaller than group_capacity which is 1 on a dual core system.

SD_POWERSAVINGS_BALANCE does /=2 to nr_running, effectively doubling the
capacity iirc. And I know some IBM dudes were toying with the idea of
playing tricks with the capacity numbers, but that never went anywhere.

> > Although I would really like to kill all those different
> > sched_*_power_savings knobs and reduce it to one.
> >
> >> If the cpu_power is
> >> higher than 1024, the cpu is no more seen out of capacity by the
> >> load_balance as soon as a short process is running and teh main result
> >> is that the small tasks will stay on the same cpu. This configuration
> >> is mainly usefull for ARM dual core system when we want to power gate
> >> one cpu. I use cyclictest to simulate such use case.
> >
> > Yeah, but that's wrong.
> 
> That's the only way I have found to gathers small task without any
> relationship on one cpu. Do you know any better solution ?

How do you know the task is 'small' ?

For that you would need to track a time-weighted effective load average
of the task and we don't have that.

[ how bad is all this u64 math on ARM btw? and when will ARM finally
  agree all this 32bit nonsense is a waste of time and silicon? ]

But yeah, the whole nr_running vs capacity thing was traditionally to
deal with spreading single tasks around. And traditional power aware
scheduling was mostly about packing those on sockets (keeps other
sockets idle) instead of spreading them around sockets (optimizes
cache).

Now I wouldn't at all mind you ripping out all that
sched_*_power_savings crap and replacing it, I doubt it actually works
anyway. I haven't got many patches on the subject, and I know I don't
have the equipment to measure power usage.

Also, the few patches I got mostly made the sched_*_power_savings mess
bigger, which I refuse to do (what sysad wants to have a 27-state space
to configure his power aware scheduling). This has mostly made people go
away instead of fixing things up :-(

As to what the replacement would have to look like, dunno, its not
something I've really thought much about, but maybe the time-weighted
stuff is the only sane approach, that combined with options on how to
spread tasks (core, socket, node, etc..).

I really think changing the load-balancer is the right way to go about
solving your power issue (hot-plugging a cpu really is an insane way to
idle a core) and I'm open to discussing what would work for you.

All I really ask is to not cobble something together, the load-balancer
is a horridly complex thing already and the last thing it needs is more
special cases that don't interact properly.

^ permalink raw reply

* [PATCH v3 1/6] iommu/core: split mapping to page sizes as supported by the hardware
From: Roedel, Joerg @ 2011-10-11 10:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAK=WgbbnuO67X46sqS87q2vw2TWq3Ekvw5p1PmXvXinQXMyowg@mail.gmail.com>

On Mon, Oct 10, 2011 at 06:49:32PM -0400, Ohad Ben-Cohen wrote:
> -int iommu_unmap(struct iommu_domain *domain, unsigned long iova, int gfp_order)
> +int iommu_unmap(struct iommu_domain *domain, unsigned long iova, int size)
>  {
> -       size_t size;
> +       int order, unmapped_size, unmapped_order, total_unmapped = 0;
> 
>         if (unlikely(domain->ops->unmap == NULL))
>                 return -ENODEV;
> 
> -       size         = PAGE_SIZE << gfp_order;
> +       /*
> +        * The virtual address, as well as the size of the mapping, must be
> +        * aligned (at least) to the size of the smallest page supported
> +        * by the hardware
> +        */
> +       if (!IS_ALIGNED(iova | size, domain->ops->min_pagesz)) {
> +               pr_err("unaligned: iova 0x%lx size 0x%x min_pagesz 0x%x\n",
> +                       iova, size, domain->ops->min_pagesz);
> +               return -EINVAL;
> +       }
> +
> +       pr_debug("unmap this: iova 0x%lx size 0x%x\n", iova, size);
> +
> +       while (size > total_unmapped) {
> +               order = get_order(size - total_unmapped);

Hmm, this actually unmaps more than requested, even in the symetric
case. Imgine the user wants to unmap a 12kb region, then order
will be 4 and this code will tell the iommu-driver to unmap 16kb.

You need to make sure that you don;t pass larger regions then requested
to the low-level driver. Some logic like in the iommu_map function
should do it.

> +
> +               unmapped_order = domain->ops->unmap(domain, iova, order);
> +               if (unmapped_order < 0)
> +                       break;
> +
> +               pr_debug("unmapped: iova 0x%lx order %d\n", iova,
> +                                                       unmapped_order);
> +
> +               unmapped_size = 0x1000UL << unmapped_order;

Please use PAGE_SIZE instead of 0x1000UL.

> 
> -       BUG_ON(!IS_ALIGNED(iova, size));
> +               iova += unmapped_size;
> +               total_unmapped += unmapped_size;
> +       }
> 
> -       return domain->ops->unmap(domain, iova, gfp_order);
> +       return total_unmapped;
>  }
>  EXPORT_SYMBOL_GPL(iommu_unmap);
> 
> diff --git a/drivers/iommu/omap-iovmm.c b/drivers/iommu/omap-iovmm.c
> index e8fdb88..4a8f761 100644
> --- a/drivers/iommu/omap-iovmm.c
> +++ b/drivers/iommu/omap-iovmm.c
> @@ -409,7 +409,6 @@ static int map_iovm_area(struct iommu_domain
> *domain, struct iovm_struct *new,
>         unsigned int i, j;
>         struct scatterlist *sg;
>         u32 da = new->da_start;
> -       int order;
> 
>         if (!domain || !sgt)
>                 return -EINVAL;
> @@ -428,12 +427,10 @@ static int map_iovm_area(struct iommu_domain
> *domain, struct iovm_struct *new,
>                 if (bytes_to_iopgsz(bytes) < 0)
>                         goto err_out;
> 
> -               order = get_order(bytes);
> -
>                 pr_debug("%s: [%d] %08x %08x(%x)\n", __func__,
>                          i, da, pa, bytes);
> 
> -               err = iommu_map(domain, da, pa, order, flags);
> +               err = iommu_map(domain, da, pa, bytes, flags);
>                 if (err)
>                         goto err_out;
> 
> @@ -448,10 +445,9 @@ err_out:
>                 size_t bytes;
> 
>                 bytes = sg->length + sg->offset;
> -               order = get_order(bytes);
> 
>                 /* ignore failures.. we're already handling one */
> -               iommu_unmap(domain, da, order);
> +               iommu_unmap(domain, da, bytes);
> 
>                 da += bytes;
>         }
> @@ -474,13 +470,11 @@ static void unmap_iovm_area(struct iommu_domain
> *domain, struct omap_iommu *obj,
>         start = area->da_start;
>         for_each_sg(sgt->sgl, sg, sgt->nents, i) {
>                 size_t bytes;
> -               int order;
> 
>                 bytes = sg->length + sg->offset;
> -               order = get_order(bytes);
> 
> -               err = iommu_unmap(domain, start, order);
> -               if (err < 0)
> +               err = iommu_unmap(domain, start, bytes);
> +               if (err < bytes)
>                         break;
> 
>                 dev_dbg(obj->dev, "%s: unmap %08x(%x) %08x\n",
> diff --git a/include/linux/iommu.h b/include/linux/iommu.h
> index 710291f..a10a86c 100644
> --- a/include/linux/iommu.h
> +++ b/include/linux/iommu.h
> @@ -48,6 +48,22 @@ struct iommu_domain {
> 
>  #ifdef CONFIG_IOMMU_API
> 
> +/**
> + * struct iommu_ops - iommu ops and capabilities
> + * @domain_init: init iommu domain
> + * @domain_destroy: destroy iommu domain
> + * @attach_dev: attach device to an iommu domain
> + * @detach_dev: detach device from an iommu domain
> + * @map: map a physically contiguous memory region to an iommu domain
> + * @unmap: unmap a physically contiguous memory region from an iommu domain
> + * @iova_to_phys: translate iova to physical address
> + * @domain_has_cap: domain capabilities query
> + * @commit: commit iommu domain
> + * @pgsize_bitmap: bitmap of supported page sizes
> + * @min_pagesz: smallest page size supported. note: this member is private
> + *             to the IOMMU core, and maintained only for efficiency sake;
> + *             drivers don't need to set it.
> + */
>  struct iommu_ops {
>         int (*domain_init)(struct iommu_domain *domain);
>         void (*domain_destroy)(struct iommu_domain *domain);
> @@ -62,6 +78,8 @@ struct iommu_ops {
>         int (*domain_has_cap)(struct iommu_domain *domain,
>                               unsigned long cap);
>         void (*commit)(struct iommu_domain *domain);
> +       unsigned long pgsize_bitmap;
> +       unsigned int min_pagesz;
>  };
> 
>  extern int bus_set_iommu(struct bus_type *bus, struct iommu_ops *ops);
> @@ -73,9 +91,9 @@ extern int iommu_attach_device(struct iommu_domain *domain,
>  extern void iommu_detach_device(struct iommu_domain *domain,
>                                 struct device *dev);
>  extern int iommu_map(struct iommu_domain *domain, unsigned long iova,
> -                    phys_addr_t paddr, int gfp_order, int prot);
> +                    phys_addr_t paddr, int size, int prot);
>  extern int iommu_unmap(struct iommu_domain *domain, unsigned long iova,
> -                      int gfp_order);
> +                      int size);
>  extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
>                                       unsigned long iova);
>  extern int iommu_domain_has_cap(struct iommu_domain *domain,
> diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c
> index ca409be..26b3199 100644
> --- a/virt/kvm/iommu.c
> +++ b/virt/kvm/iommu.c
> @@ -111,7 +111,7 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct
> kvm_memory_slot *slot)
> 
>                 /* Map into IO address space */
>                 r = iommu_map(domain, gfn_to_gpa(gfn), pfn_to_hpa(pfn),
> -                             get_order(page_size), flags);
> +                             page_size, flags);
>                 if (r) {
>                         printk(KERN_ERR "kvm_iommu_map_address:"
>                                "iommu failed to map pfn=%llx\n", pfn);
> @@ -292,15 +292,15 @@ static void kvm_iommu_put_pages(struct kvm *kvm,
> 
>         while (gfn < end_gfn) {
>                 unsigned long unmap_pages;
> -               int order;
> +               int size;
> 
>                 /* Get physical address */
>                 phys = iommu_iova_to_phys(domain, gfn_to_gpa(gfn));
>                 pfn  = phys >> PAGE_SHIFT;
> 
>                 /* Unmap address from IO address space */
> -               order       = iommu_unmap(domain, gfn_to_gpa(gfn), 0);
> -               unmap_pages = 1ULL << order;
> +               size       = iommu_unmap(domain, gfn_to_gpa(gfn), PAGE_SIZE);
> +               unmap_pages = 1ULL << get_order(size);
> 
>                 /* Unpin all pages we just unmapped to not leak any memory */
>                 kvm_unpin_pages(kvm, pfn, unmap_pages);

-- 
AMD Operating System Research Center

Advanced Micro Devices GmbH Einsteinring 24 85609 Dornach
General Managers: Alberto Bozzo, Andrew Bowd
Registration: Dornach, Landkr. Muenchen; Registerger. Muenchen, HRB Nr. 43632

^ permalink raw reply

* [PATCH v8 0/3] Add support for tegra2 based ventana board
From: Peter De Schrijver @ 2011-10-11 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

This patch set adds support for the tegra2 based ventana development board.

Boot tested on ventana.                                                                                                                               

Uses a table based approach to select the correct init function.

Provoke kernel warning when no suitable pinmux table can be found.

Peter De Schrijver (3):
  arm/tegra: prepare Seaboard pinmux code for derived boards
  arm/tegra: add support for ventana pinmuxing
  arm/tegra: device tree support for ventana board

 arch/arm/boot/dts/tegra-ventana.dts         |   32 ++++++++++++++
 arch/arm/mach-tegra/Kconfig                 |    6 +++
 arch/arm/mach-tegra/Makefile                |    1 +
 arch/arm/mach-tegra/Makefile.boot           |    1 +
 arch/arm/mach-tegra/board-dt.c              |    5 ++-
 arch/arm/mach-tegra/board-seaboard-pinmux.c |   63 ++++++++++++++++++++++++---
 6 files changed, 101 insertions(+), 7 deletions(-)
 create mode 100644 arch/arm/boot/dts/tegra-ventana.dts

^ permalink raw reply

* [PATCH v8 1/3] arm/tegra: prepare Seaboard pinmux code for derived boards
From: Peter De Schrijver @ 2011-10-11 10:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1318329909-32601-1-git-send-email-pdeschrijver@nvidia.com>

This patch splits out the common part of pinmux and GPIO initialization for
seaboard and derived boards. This code is based on work done by Jong Kim
<jongk@nvidia.com>.

Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 arch/arm/mach-tegra/board-seaboard-pinmux.c |   14 ++++++++++----
 1 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-tegra/board-seaboard-pinmux.c b/arch/arm/mach-tegra/board-seaboard-pinmux.c
index 74f78b7..b31c765 100644
--- a/arch/arm/mach-tegra/board-seaboard-pinmux.c
+++ b/arch/arm/mach-tegra/board-seaboard-pinmux.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2010 NVIDIA Corporation
+ * Copyright (C) 2010,2011 NVIDIA Corporation
+ * Copyright (C) 2011 Google, Inc.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -160,7 +161,7 @@ static __initdata struct tegra_pingroup_config seaboard_pinmux[] = {
 
 
 
-static struct tegra_gpio_table gpio_table[] = {
+static struct tegra_gpio_table common_gpio_table[] = {
 	{ .gpio = TEGRA_GPIO_SD2_CD,		.enable = true },
 	{ .gpio = TEGRA_GPIO_SD2_WP,		.enable = true },
 	{ .gpio = TEGRA_GPIO_SD2_POWER,		.enable = true },
@@ -171,12 +172,17 @@ static struct tegra_gpio_table gpio_table[] = {
 	{ .gpio = TEGRA_GPIO_USB1,		.enable = true },
 };
 
-void __init seaboard_pinmux_init(void)
+static void __init seaboard_common_pinmux_init(void)
 {
 	tegra_pinmux_config_table(seaboard_pinmux, ARRAY_SIZE(seaboard_pinmux));
 
 	tegra_drive_pinmux_config_table(seaboard_drive_pinmux,
 					ARRAY_SIZE(seaboard_drive_pinmux));
 
-	tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
+	tegra_gpio_config(common_gpio_table, ARRAY_SIZE(common_gpio_table));
+}
+
+void __init seaboard_pinmux_init(void)
+{
+	seaboard_common_pinmux_init();
 }
-- 
1.7.7.rc0.72.g4b5ea.dirty

^ permalink raw reply related

* [PATCH v8 2/3] arm/tegra: add support for ventana pinmuxing
From: Peter De Schrijver @ 2011-10-11 10:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1318329909-32601-1-git-send-email-pdeschrijver@nvidia.com>

Add support for ventana pinmuxing as a seaboard derivative. This is a cut down
version of work done by Jong Kim <jongk@nvidia.com>.

Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 arch/arm/mach-tegra/Makefile                |    1 +
 arch/arm/mach-tegra/board-seaboard-pinmux.c |   49 +++++++++++++++++++++++++-
 2 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index f11b910..91a07e1 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -31,6 +31,7 @@ obj-${CONFIG_MACH_SEABOARD}             += board-seaboard-pinmux.o
 
 obj-${CONFIG_MACH_TEGRA_DT}             += board-dt.o
 obj-${CONFIG_MACH_TEGRA_DT}             += board-harmony-pinmux.o
+obj-${CONFIG_MACH_TEGRA_DT}             += board-seaboard-pinmux.o
 
 obj-${CONFIG_MACH_TRIMSLICE}            += board-trimslice.o
 obj-${CONFIG_MACH_TRIMSLICE}            += board-trimslice-pinmux.o
diff --git a/arch/arm/mach-tegra/board-seaboard-pinmux.c b/arch/arm/mach-tegra/board-seaboard-pinmux.c
index b31c765..b62b04d 100644
--- a/arch/arm/mach-tegra/board-seaboard-pinmux.c
+++ b/arch/arm/mach-tegra/board-seaboard-pinmux.c
@@ -158,8 +158,26 @@ static __initdata struct tegra_pingroup_config seaboard_pinmux[] = {
 	{TEGRA_PINGROUP_XM2D,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 };
 
-
-
+static __initdata struct tegra_pingroup_config ventana_pinmux[] = {
+	{TEGRA_PINGROUP_DAP3, TEGRA_MUX_DAP3,     TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DDC,  TEGRA_MUX_RSVD2,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTA,  TEGRA_MUX_VI,       TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTB,  TEGRA_MUX_VI,       TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTC,  TEGRA_MUX_VI,       TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTD,  TEGRA_MUX_VI,       TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GMD,  TEGRA_MUX_SFLASH,   TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LPW0, TEGRA_MUX_RSVD4,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LPW2, TEGRA_MUX_RSVD4,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LSC1, TEGRA_MUX_RSVD4,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LSCK, TEGRA_MUX_RSVD4,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSDA, TEGRA_MUX_RSVD4,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_PTA,  TEGRA_MUX_RSVD2,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SLXC, TEGRA_MUX_SDIO3,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SLXK, TEGRA_MUX_SDIO3,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SPIA, TEGRA_MUX_GMI,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIC, TEGRA_MUX_GMI,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIG, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+};
 
 static struct tegra_gpio_table common_gpio_table[] = {
 	{ .gpio = TEGRA_GPIO_SD2_CD,		.enable = true },
@@ -172,6 +190,26 @@ static struct tegra_gpio_table common_gpio_table[] = {
 	{ .gpio = TEGRA_GPIO_USB1,		.enable = true },
 };
 
+static void __init update_pinmux(struct tegra_pingroup_config *newtbl, int size)
+{
+	int i, j;
+	struct tegra_pingroup_config *new_pingroup, *base_pingroup;
+
+	/* Update base seaboard pinmux table with secondary board
+	 * specific pinmux table table.
+	 */
+	for (i = 0; i < size; i++) {
+		new_pingroup = &newtbl[i];
+		for (j = 0; j < ARRAY_SIZE(seaboard_pinmux); j++) {
+			base_pingroup = &seaboard_pinmux[j];
+			if (new_pingroup->pingroup == base_pingroup->pingroup) {
+				*base_pingroup = *new_pingroup;
+				break;
+			}
+		}
+	}
+}
+
 static void __init seaboard_common_pinmux_init(void)
 {
 	tegra_pinmux_config_table(seaboard_pinmux, ARRAY_SIZE(seaboard_pinmux));
@@ -186,3 +224,10 @@ void __init seaboard_pinmux_init(void)
 {
 	seaboard_common_pinmux_init();
 }
+
+void __init ventana_pinmux_init(void)
+{
+	update_pinmux(ventana_pinmux, ARRAY_SIZE(ventana_pinmux));
+	seaboard_common_pinmux_init();
+}
+
-- 
1.7.7.rc0.72.g4b5ea.dirty

^ permalink raw reply related

* [PATCH v8 3/3] arm/tegra: device tree support for ventana board
From: Peter De Schrijver @ 2011-10-11 10:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1318329909-32601-1-git-send-email-pdeschrijver@nvidia.com>

Change-Id: I5ed18750e6a8aa3242dae4bcd7165cfd819356d2
Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 arch/arm/boot/dts/tegra-ventana.dts |   32 ++++++++++++++++++++++++++++++++
 arch/arm/mach-tegra/Kconfig         |    6 ++++++
 arch/arm/mach-tegra/Makefile.boot   |    1 +
 arch/arm/mach-tegra/board-dt.c      |   26 +++++++++++++++++++++-----
 4 files changed, 60 insertions(+), 5 deletions(-)
 create mode 100644 arch/arm/boot/dts/tegra-ventana.dts

diff --git a/arch/arm/boot/dts/tegra-ventana.dts b/arch/arm/boot/dts/tegra-ventana.dts
new file mode 100644
index 0000000..9b29a62
--- /dev/null
+++ b/arch/arm/boot/dts/tegra-ventana.dts
@@ -0,0 +1,32 @@
+/dts-v1/;
+
+/memreserve/ 0x1c000000 0x04000000;
+/include/ "tegra20.dtsi"
+
+/ {
+	model = "NVIDIA Tegra2 Ventana evaluation board";
+	compatible = "nvidia,ventana", "nvidia,tegra20";
+
+	chosen {
+		bootargs = "vmalloc=192M video=tegrafb console=ttyS0,115200n8 root=/dev/ram rdinit=/sbin/init";
+	};
+
+	memory {
+		reg = < 0x00000000 0x40000000 >;
+	};
+
+	serial at 70006300 {
+		clock-frequency = < 216000000 >;
+	};
+
+	sdhci at c8000400 {
+		cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+		wp-gpios = <&gpio 57 0>; /* gpio PH1 */
+		power-gpios = <&gpio 155 0>; /* gpio PT3 */
+	};
+
+	sdhci at c8000600 {
+		power-gpios = <&gpio 70 0>; /* gpio PI6 */
+		support-8bit;
+	};
+};
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index d82ebab..91aff7c 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -69,6 +69,12 @@ config MACH_WARIO
        help
          Support for the Wario version of Seaboard
 
+config MACH_VENTANA
+       bool "Ventana board"
+       select MACH_TEGRA_DT
+       help
+         Support for the nVidia Ventana development platform
+
 choice
         prompt "Low-level debug console UART"
         default TEGRA_DEBUG_UART_NONE
diff --git a/arch/arm/mach-tegra/Makefile.boot b/arch/arm/mach-tegra/Makefile.boot
index 5e870d2..bd12c9f 100644
--- a/arch/arm/mach-tegra/Makefile.boot
+++ b/arch/arm/mach-tegra/Makefile.boot
@@ -4,3 +4,4 @@ initrd_phys-$(CONFIG_ARCH_TEGRA_2x_SOC)	:= 0x00800000
 
 dtb-$(CONFIG_MACH_HARMONY) += tegra-harmony.dtb
 dtb-$(CONFIG_MACH_SEABOARD) += tegra-seaboard.dtb
+dtb-$(CONFIG_MACH_VENTANA) += tegra-ventana.dtb
diff --git a/arch/arm/mach-tegra/board-dt.c b/arch/arm/mach-tegra/board-dt.c
index 9f47e04..96287a2 100644
--- a/arch/arm/mach-tegra/board-dt.c
+++ b/arch/arm/mach-tegra/board-dt.c
@@ -47,7 +47,7 @@
 
 void harmony_pinmux_init(void);
 void seaboard_pinmux_init(void);
-
+void ventana_pinmux_init(void);
 
 struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC1_BASE, "sdhci-tegra.0", NULL),
@@ -80,9 +80,19 @@ static struct of_device_id tegra_dt_gic_match[] __initdata = {
 	{}
 };
 
+static struct {
+	char *machine;
+	void (*init)(void);
+} pinmux_configs[] = {
+	{ "nvidia,harmony", harmony_pinmux_init },
+	{ "nvidia,seaboard", seaboard_pinmux_init },
+	{ "nvidia,ventana", ventana_pinmux_init },
+};
+
 static void __init tegra_dt_init(void)
 {
 	struct device_node *node;
+	int i;
 
 	node = of_find_matching_node_by_address(NULL, tegra_dt_gic_match,
 						TEGRA_ARM_INT_DIST_BASE);
@@ -91,10 +101,15 @@ static void __init tegra_dt_init(void)
 
 	tegra_clk_init_from_table(tegra_dt_clk_init_table);
 
-	if (of_machine_is_compatible("nvidia,harmony"))
-		harmony_pinmux_init();
-	else if (of_machine_is_compatible("nvidia,seaboard"))
-		seaboard_pinmux_init();
+	for (i = 0; i < ARRAY_SIZE(pinmux_configs); i++) {
+		if (of_machine_is_compatible(pinmux_configs[i].machine)) {
+			pinmux_configs[i].init();
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(pinmux_configs))
+		WARN(1, "Unknown platform! Pinmuxing not initialized\n");
 
 	/*
 	 * Finished with the static registrations now; fill in the missing
@@ -106,6 +121,7 @@ static void __init tegra_dt_init(void)
 static const char * tegra_dt_board_compat[] = {
 	"nvidia,harmony",
 	"nvidia,seaboard",
+	"nvidia,ventana",
 	NULL
 };
 
-- 
1.7.7.rc0.72.g4b5ea.dirty

^ permalink raw reply related

* [PATCH] rtc: rtc-s3c: Add device tree support
From: Kukjin Kim @ 2011-10-11 10:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAJuYYwQdeD=DEFSBqTTJM_EQcc517LPDy4w-N+mbHdH8Eqh=Dg@mail.gmail.com>

Thomas Abraham wrote:
> 
> On 3 September 2011 21:19, Thomas Abraham <thomas.abraham@linaro.org>
> wrote:
> > Add device tree based discovery support for Samsung's rtc controller.
> >
> > Cc: Ben Dooks <ben-linux@fluff.org>
> > Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
> > ---
> > ?Documentation/devicetree/bindings/rtc/s3c-rtc.txt | ? 20
> ++++++++++++++++++++
> > ?drivers/rtc/rtc-s3c.c ? ? ? ? ? ? ? ? ? ? ? ? ? ? | ? 21
> ++++++++++++++++++++-
> > ?2 files changed, 40 insertions(+), 1 deletions(-)
> > ?create mode 100644 Documentation/devicetree/bindings/rtc/s3c-rtc.txt
> 
> Ping. Any comments for this patch? If this looks fine, can this be
> considered for 3.2 merge via the Samsung kernel tree.
> 
(Cc'ed Alessandro Zummo who is RTC Subsystem maintainer)

I'm ok with this, so if this can be got the ack from Grant and Alessandro,
will take this.

> >
> > diff --git a/Documentation/devicetree/bindings/rtc/s3c-rtc.txt
> b/Documentation/devicetree/bindings/rtc/s3c-rtc.txt
> > new file mode 100644
> > index 0000000..90ec45f
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/rtc/s3c-rtc.txt
> > @@ -0,0 +1,20 @@
> > +* Samsung's S3C Real Time Clock controller
> > +
> > +Required properties:
> > +- compatible: should be one of the following.
> > + ? ?* "samsung,s3c2410-rtc" - for controllers compatible with s3c2410
rtc.
> > + ? ?* "samsung,s3c6410-rtc" - for controllers compatible with s3c6410
rtc.
> > +- reg: physical base address of the controller and length of memory
mapped
> > + ?region.
> > +- interrupts: Two interrupt numbers to the cpu should be specified.
First
> > + ?interrupt number is the rtc alarm interupt and second interrupt
number
> > + ?is the rtc tick interrupt. The number of cells representing a
interrupt
> > + ?depends on the parent interrupt controller.
> > +
> > +Example:
> > +
> > + ? ? ? rtc at 10070000 {
> > + ? ? ? ? ? ? ? compatible = "samsung,s3c6410-rtc";
> > + ? ? ? ? ? ? ? reg = <0x10070000 0x100>;
> > + ? ? ? ? ? ? ? interrupts = <44 0 45 0>;
> > + ? ? ? };
> > diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
> > index 4e7c04e..29f928c 100644
> > --- a/drivers/rtc/rtc-s3c.c
> > +++ b/drivers/rtc/rtc-s3c.c
> > @@ -25,6 +25,7 @@
> > ?#include <linux/clk.h>
> > ?#include <linux/log2.h>
> > ?#include <linux/slab.h>
> > +#include <linux/of.h>
> >
> > ?#include <mach/hardware.h>
> > ?#include <asm/uaccess.h>
> > @@ -481,7 +482,13 @@ static int __devinit s3c_rtc_probe(struct
> platform_device *pdev)
> > ? ? ? ? ? ? ? ?goto err_nortc;
> > ? ? ? ?}
> >
> > - ? ? ? s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data;
> > +#ifdef CONFIG_OF
> > + ? ? ? if (pdev->dev.of_node)
> > + ? ? ? ? ? ? ? s3c_rtc_cpu_type = of_device_is_compatible(pdev-
> >dev.of_node,
> > + ? ? ? ? ? ? ? ? ? ? ? "samsung,s3c6410-rtc") ? TYPE_S3C64XX :
> TYPE_S3C2410;
> > + ? ? ? else
> > +#endif
> > + ? ? ? ? ? ? ? s3c_rtc_cpu_type =
platform_get_device_id(pdev)->driver_data;
> >
> > ? ? ? ?/* Check RTC Time */
> >
> > @@ -603,6 +610,17 @@ static int s3c_rtc_resume(struct platform_device
*pdev)
> > ?#define s3c_rtc_resume ?NULL
> > ?#endif
> >
> > +#ifdef CONFIG_OF
> > +static const struct of_device_id s3c_rtc_dt_match[] = {
> > +       { .compatible = "samsung,s3c2410-rtc" },
     ^^^^^^^
> > +       { .compatible = "samsung,s3c6410-rtc" },
     ^^^^^^^
> > +       {},
     ^^^^^^^
should be Tab?

> > +};
> > +MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match);
> > +#else
> > +#define s3c_rtc_dt_match NULL
> > +#endif
> > +
> > ?static struct platform_device_id s3c_rtc_driver_ids[] = {
> > ? ? ? ?{
> > ? ? ? ? ? ? ? ?.name ? ? ? ? ? = "s3c2410-rtc",
> > @@ -625,6 +643,7 @@ static struct platform_driver s3c_rtc_driver = {
> > ? ? ? ?.driver ? ? ? ? = {
> > ? ? ? ? ? ? ? ?.name ? = "s3c-rtc",
> > ? ? ? ? ? ? ? ?.owner ?= THIS_MODULE,
> > +               .of_match_table = s3c_rtc_dt_match,
     ^^^^^^^^^^^^^^^
Same as above...

But I know, Thomas' original patch has no problem...probably when ping,
happened above.

> > ? ? ? ?},
> > ?};
> >
> > --

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

^ permalink raw reply

* [PATCH] ARM: S3C64XX: Enable TCM support
From: Kukjin Kim @ 2011-10-11 10:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACRpkdYtH4SCk3o3W84u+pLwzaXnmU1OP7p631bC08QnP2bR9A@mail.gmail.com>

Linus Walleij wrote:
> 
> On Mon, Oct 10, 2011 at 12:27 PM, Mark Brown
> <broonie@opensource.wolfsonmicro.com> wrote:
> 
> > The S3C64xx CPUs have TCMs so enable the kernel support for it on these
> > systems.
> >
> > Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> 
> Cool! How big are they each, i.e. dmesg?
> 
> Acked-by: Linus Walleij <linus.walleij@linaro.org>
> 
Applied, thanks :)

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

^ permalink raw reply

* [Linaro-mm-sig] [PATCHv16 0/9] Contiguous Memory Allocator
From: Marek Szyprowski @ 2011-10-11 10:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4E93F088.60006@stericsson.com>

Hello,

On Tuesday, October 11, 2011 9:30 AM Maxime Coquelin wrote:

> On 10/11/2011 09:17 AM, Marek Szyprowski wrote:
> > On Monday, October 10, 2011 2:08 PM Maxime Coquelin wrote:
> >
> >       During our stress tests, we encountered some problems :
> >
> >       1) Contiguous allocation lockup:
> >           When system RAM is full of Anon pages, if we try to allocate a
> > contiguous buffer greater than the min_free value, we face a
> > dma_alloc_from_contiguous lockup.
> >           The expected result would be dma_alloc_from_contiguous() to fail.
> >           The problem is reproduced systematically on our side.
> > Thanks for the report. Do you use Android's lowmemorykiller? I haven't
> > tested CMA on Android kernel yet. I have no idea how it will interfere
> > with Android patches.
> >
> 
> The software used for this test (v16) is a generic 3.0 Kernel and a
> minimal filesystem using Busybox.

I'm really surprised. Could you elaborate a bit how to trigger this issue?
I've did several tests and I never get a lockup. Allocation failed from time
to time though.

> With v15 patchset, I also tested it with Android.
> IIRC, sometimes the lowmemorykiller succeed to get free space and the
> contiguous allocation succeed, sometimes we faced  the lockup.
> 
> >>       2) Contiguous allocation fail:
> >>           We have developed a small driver and a shell script to
> >> allocate/release contiguous buffers.
> >>           Sometimes, dma_alloc_from_contiguous() fails to allocate the
> >> contiguous buffer (about once every 30 runs).
> >>           We have 270MB Memory passed to the kernel in our configuration,
> >> and the CMA pool is 90MB large.
> >>           In this setup, the overall memory is either free or full of
> >> reclaimable pages.
> > Yeah. We also did such stress tests recently and faced this issue. I've
> > spent some time investigating it but I have no solution yet.
> >
> > The problem is caused by a page, which is put in the CMA area. This page
> > is movable, but it's address space provides no 'migratepage' method. In
> > such case mm subsystem uses fallback_migrate_page() function. Sadly this
> > function only returns -EAGAIN. The migration loops a few times over it
> > and fails causing the fail in the allocation procedure.
> >
> > We are investing now which kernel code created/allocated such problematic

s/investing/investigating

> > pages and how to add real migration support for them.
> >
> 
> Ok, thanks for pointing this out.

We found this issue very recently. I'm still surprised that we did not notice 
it during system testing.

Best regards
-- 
Marek Szyprowski
Samsung Poland R&D Center

^ permalink raw reply

* [PATCH v4 0/3] add Atmel ISI, ov2640 support for sam9m10/sam9g45
From: Josh Wu @ 2011-10-11 11:03 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, all

Accroding to the comments from Guennadi, please see below the changes since V3:
1. Move isi_mck registration to at91_add_device_isi, but the user has a chance to or not to use the Programmable clock of the SoC.
2. In board file, e.g. board-sam9m10g45ek.c, user can pass a boolean to at91_add_device_isi, so that the SoC programmable clock can be used or not.

To summary, programmable clock is managed in SoC level. The user can decide to use or not to use SoC clock as the sensor MCK at board level. 
In later case, user has to provide a clock source named "isi_mck"

Best Regards,
Josh Wu

^ permalink raw reply

* [PATCH v4 1/3] [media] at91: add code to enable/disable ISI_MCK clock
From: Josh Wu @ 2011-10-11 11:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1318331020-22031-1-git-send-email-josh.wu@atmel.com>

This patch
- add ISI_MCK clock enable/disable code.
- change field name in isi_platform_data structure

Signed-off-by: Josh Wu <josh.wu@atmel.com>
---
 drivers/media/video/atmel-isi.c |   34 +++++++++++++++++++++++++++++++---
 include/media/atmel-isi.h       |    4 +++-
 2 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/drivers/media/video/atmel-isi.c b/drivers/media/video/atmel-isi.c
index 774715d..0617163 100644
--- a/drivers/media/video/atmel-isi.c
+++ b/drivers/media/video/atmel-isi.c
@@ -90,7 +90,10 @@ struct atmel_isi {
 	struct isi_dma_desc		dma_desc[MAX_BUFFER_NUM];
 
 	struct completion		complete;
+	/* ISI peripherial clock */
 	struct clk			*pclk;
+	/* ISI_MCK, feed to camera sensor to generate pixel clock */
+	struct clk			*mck;
 	unsigned int			irq;
 
 	struct isi_platform_data	*pdata;
@@ -773,6 +776,12 @@ static int isi_camera_add_device(struct soc_camera_device *icd)
 	if (ret)
 		return ret;
 
+	ret = clk_enable(isi->mck);
+	if (ret) {
+		clk_disable(isi->pclk);
+		return ret;
+	}
+
 	isi->icd = icd;
 	dev_dbg(icd->parent, "Atmel ISI Camera driver attached to camera %d\n",
 		 icd->devnum);
@@ -786,6 +795,7 @@ static void isi_camera_remove_device(struct soc_camera_device *icd)
 
 	BUG_ON(icd != isi->icd);
 
+	clk_disable(isi->mck);
 	clk_disable(isi->pclk);
 	isi->icd = NULL;
 
@@ -869,7 +879,7 @@ static int isi_camera_set_bus_param(struct soc_camera_device *icd, u32 pixfmt)
 
 	if (isi->pdata->has_emb_sync)
 		cfg1 |= ISI_CFG1_EMB_SYNC;
-	if (isi->pdata->isi_full_mode)
+	if (isi->pdata->full_mode)
 		cfg1 |= ISI_CFG1_FULL_MODE;
 
 	isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS);
@@ -907,6 +917,7 @@ static int __devexit atmel_isi_remove(struct platform_device *pdev)
 			isi->fb_descriptors_phys);
 
 	iounmap(isi->regs);
+	clk_put(isi->mck);
 	clk_put(isi->pclk);
 	kfree(isi);
 
@@ -925,7 +936,7 @@ static int __devinit atmel_isi_probe(struct platform_device *pdev)
 	struct isi_platform_data *pdata;
 
 	pdata = dev->platform_data;
-	if (!pdata || !pdata->data_width_flags) {
+	if (!pdata || !pdata->data_width_flags || !pdata->mck_hz) {
 		dev_err(&pdev->dev,
 			"No config available for Atmel ISI\n");
 		return -EINVAL;
@@ -954,6 +965,21 @@ static int __devinit atmel_isi_probe(struct platform_device *pdev)
 	INIT_LIST_HEAD(&isi->video_buffer_list);
 	INIT_LIST_HEAD(&isi->dma_desc_head);
 
+	/* Get ISI_MCK, provided by programmable clock or external clock */
+	isi->mck = clk_get(dev, "isi_mck");
+	if (IS_ERR_OR_NULL(isi->mck)) {
+		dev_err(dev, "Failed to get isi_mck\n");
+		ret = PTR_ERR(isi->mck);
+		if (isi->mck == NULL)
+			ret = -EINVAL;
+		goto err_alloc_descriptors;
+	}
+
+	/* Set ISI_MCK's frequency, it should be faster than pixel clock */
+	ret = clk_set_rate(isi->mck, pdata->mck_hz);
+	if (ret < 0)
+		goto err_set_mck_rate;
+
 	isi->p_fb_descriptors = dma_alloc_coherent(&pdev->dev,
 				sizeof(struct fbd) * MAX_BUFFER_NUM,
 				&isi->fb_descriptors_phys,
@@ -961,7 +987,7 @@ static int __devinit atmel_isi_probe(struct platform_device *pdev)
 	if (!isi->p_fb_descriptors) {
 		ret = -ENOMEM;
 		dev_err(&pdev->dev, "Can't allocate descriptors!\n");
-		goto err_alloc_descriptors;
+		goto err_set_mck_rate;
 	}
 
 	for (i = 0; i < MAX_BUFFER_NUM; i++) {
@@ -1023,6 +1049,8 @@ err_alloc_ctx:
 			sizeof(struct fbd) * MAX_BUFFER_NUM,
 			isi->p_fb_descriptors,
 			isi->fb_descriptors_phys);
+err_set_mck_rate:
+	clk_put(isi->mck);
 err_alloc_descriptors:
 	kfree(isi);
 err_alloc_isi:
diff --git a/include/media/atmel-isi.h b/include/media/atmel-isi.h
index 26cece5..6568230 100644
--- a/include/media/atmel-isi.h
+++ b/include/media/atmel-isi.h
@@ -110,10 +110,12 @@ struct isi_platform_data {
 	u8 hsync_act_low;
 	u8 vsync_act_low;
 	u8 pclk_act_falling;
-	u8 isi_full_mode;
+	u8 full_mode;
 	u32 data_width_flags;
 	/* Using for ISI_CFG1 */
 	u32 frate;
+	/* Using for ISI_MCK */
+	u32 mck_hz;
 };
 
 #endif /* __ATMEL_ISI_H__ */
-- 
1.6.3.3

^ permalink raw reply related

* [PATCH v4 2/3] at91: add parameters for at91_add_device_isi function
From: Josh Wu @ 2011-10-11 11:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1318331020-22031-1-git-send-email-josh.wu@atmel.com>

This patch add parameters for at91_add_device_isi function

Signed-off-by: Josh Wu <josh.wu@atmel.com>
---
 arch/arm/mach-at91/at91sam9263_devices.c |   13 ++++++++++---
 arch/arm/mach-at91/include/mach/board.h  |    4 +++-
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index a050f41..7990e8e 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -885,7 +885,8 @@ static struct platform_device at91sam9263_isi_device = {
 	.num_resources	= ARRAY_SIZE(isi_resources),
 };
 
-void __init at91_add_device_isi(void)
+void __init at91_add_device_isi(struct isi_platform_data * data,
+		bool use_pck_as_mck)
 {
 	at91_set_A_periph(AT91_PIN_PE0, 0);	/* ISI_D0 */
 	at91_set_A_periph(AT91_PIN_PE1, 0);	/* ISI_D1 */
@@ -898,14 +899,20 @@ void __init at91_add_device_isi(void)
 	at91_set_A_periph(AT91_PIN_PE8, 0);	/* ISI_PCK */
 	at91_set_A_periph(AT91_PIN_PE9, 0);	/* ISI_HSYNC */
 	at91_set_A_periph(AT91_PIN_PE10, 0);	/* ISI_VSYNC */
-	at91_set_B_periph(AT91_PIN_PE11, 0);	/* ISI_MCK (PCK3) */
 	at91_set_B_periph(AT91_PIN_PE12, 0);	/* ISI_PD8 */
 	at91_set_B_periph(AT91_PIN_PE13, 0);	/* ISI_PD9 */
 	at91_set_B_periph(AT91_PIN_PE14, 0);	/* ISI_PD10 */
 	at91_set_B_periph(AT91_PIN_PE15, 0);	/* ISI_PD11 */
+
+	if (use_pck_as_mck) {
+		at91_set_B_periph(AT91_PIN_PE11, 0);	/* ISI_MCK (PCK3) */
+
+		/* TODO: register the PCK for ISI_MCK and set its parent */
+	}
 }
 #else
-void __init at91_add_device_isi(void) {}
+void __init at91_add_device_isi(struct isi_platform_data * data,
+		int use_pck_as_mck) {}
 #endif
 
 
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
index ed544a0..731c449 100644
--- a/arch/arm/mach-at91/include/mach/board.h
+++ b/arch/arm/mach-at91/include/mach/board.h
@@ -183,7 +183,9 @@ extern void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data);
 extern void __init at91_add_device_ac97(struct ac97c_platform_data *data);
 
  /* ISI */
-extern void __init at91_add_device_isi(void);
+struct isi_platform_data;
+extern void __init at91_add_device_isi(struct isi_platform_data *data,
+		bool use_pck_as_mck);
 
  /* Touchscreen Controller */
 struct at91_tsadcc_data {
-- 
1.6.3.3

^ permalink raw reply related

* [PATCH v4 3/3] at91: add Atmel ISI and ov2640 support on sam9m10/sam9g45 board
From: Josh Wu @ 2011-10-11 11:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1318331020-22031-1-git-send-email-josh.wu@atmel.com>

This patch add:
- ov2640 sensor in sam9m10/sam9g45 board.
- support to use PCK as ISI_MCK. PCK's parent is managed in SoC level, e.g. at91sam9g45_devices.c

Signed-off-by: Josh Wu <josh.wu@atmel.com>
---
 arch/arm/mach-at91/at91sam9g45_devices.c |   98 +++++++++++++++++++++++++++++-
 arch/arm/mach-at91/board-sam9m10g45ek.c  |   85 +++++++++++++++++++++++++-
 2 files changed, 180 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 600bffb..00e6a7f 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -16,7 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/i2c-gpio.h>
 #include <linux/atmel-mci.h>
-
+#include <linux/clk.h>
 #include <linux/fb.h>
 #include <video/atmel_lcdc.h>
 
@@ -28,7 +28,10 @@
 #include <mach/at_hdmac.h>
 #include <mach/atmel-mci.h>
 
+#include <media/atmel-isi.h>
+
 #include "generic.h"
+#include "clock.h"
 
 
 /* --------------------------------------------------------------------
@@ -863,6 +866,99 @@ void __init at91_add_device_ac97(struct ac97c_platform_data *data)
 void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
 #endif
 
+/* --------------------------------------------------------------------
+ *  Image Sensor Interface
+ * -------------------------------------------------------------------- */
+#if defined(CONFIG_VIDEO_ATMEL_ISI) || defined(CONFIG_VIDEO_ATMEL_ISI_MODULE)
+static u64 isi_dmamask = DMA_BIT_MASK(32);
+static struct isi_platform_data isi_data;
+
+struct resource isi_resources[] = {
+	[0] = {
+		.start	= AT91SAM9G45_BASE_ISI,
+		.end	= AT91SAM9G45_BASE_ISI + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9G45_ID_ISI,
+		.end	= AT91SAM9G45_ID_ISI,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9g45_isi_device = {
+	.name		= "atmel_isi",
+	.id		= 0,
+	.dev		= {
+			.dma_mask		= &isi_dmamask,
+			.coherent_dma_mask	= DMA_BIT_MASK(32),
+			.platform_data		= &isi_data,
+	},
+	.resource	= isi_resources,
+	.num_resources	= ARRAY_SIZE(isi_resources),
+};
+
+static struct clk_lookup isi_mck_lookups[] = {
+	CLKDEV_CON_DEV_ID("isi_mck", "atmel_isi.0", NULL),
+};
+
+void __init at91_add_device_isi(struct isi_platform_data * data,
+		bool use_pck_as_mck)
+{
+	struct clk *pck;
+	struct clk *parent;
+
+	if (!data)
+		return;
+	isi_data = *data;
+
+	at91_set_A_periph(AT91_PIN_PB20, 0);	/* ISI_D0 */
+	at91_set_A_periph(AT91_PIN_PB21, 0);	/* ISI_D1 */
+	at91_set_A_periph(AT91_PIN_PB22, 0);	/* ISI_D2 */
+	at91_set_A_periph(AT91_PIN_PB23, 0);	/* ISI_D3 */
+	at91_set_A_periph(AT91_PIN_PB24, 0);	/* ISI_D4 */
+	at91_set_A_periph(AT91_PIN_PB25, 0);	/* ISI_D5 */
+	at91_set_A_periph(AT91_PIN_PB26, 0);	/* ISI_D6 */
+	at91_set_A_periph(AT91_PIN_PB27, 0);	/* ISI_D7 */
+	at91_set_A_periph(AT91_PIN_PB28, 0);	/* ISI_PCK */
+	at91_set_A_periph(AT91_PIN_PB30, 0);	/* ISI_HSYNC */
+	at91_set_A_periph(AT91_PIN_PB29, 0);	/* ISI_VSYNC */
+	at91_set_B_periph(AT91_PIN_PB8, 0);	/* ISI_PD8 */
+	at91_set_B_periph(AT91_PIN_PB9, 0);	/* ISI_PD9 */
+	at91_set_B_periph(AT91_PIN_PB10, 0);	/* ISI_PD10 */
+	at91_set_B_periph(AT91_PIN_PB11, 0);	/* ISI_PD11 */
+
+	platform_device_register(&at91sam9g45_isi_device);
+
+	if (use_pck_as_mck) {
+		at91_set_B_periph(AT91_PIN_PB31, 0);	/* ISI_MCK (PCK1) */
+
+		pck = clk_get(NULL, "pck1");
+		parent = clk_get(NULL, "plla");
+
+		if (IS_ERR(pck) || IS_ERR(parent))
+			BUG();
+
+		if (clk_set_parent(pck, parent))
+			printk(KERN_ERR "Failed to set PCK's parent\n");
+		else {
+			/* Register PCK as ISI_MCK */
+			isi_mck_lookups->clk = pck;
+			clkdev_add_table(isi_mck_lookups,
+					ARRAY_SIZE(isi_mck_lookups));
+		}
+
+		clk_put(pck);
+		clk_put(parent);
+	}
+
+	return;
+}
+#else
+void __init at91_add_device_isi(struct isi_platform_data * data,
+		int use_pck_as_mck) {}
+#endif
+
 
 /* --------------------------------------------------------------------
  *  LCD Controller
diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
index ad234cc..068464c 100644
--- a/arch/arm/mach-at91/board-sam9m10g45ek.c
+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
@@ -23,11 +23,13 @@
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
 #include <linux/leds.h>
-#include <linux/clk.h>
 #include <linux/atmel-mci.h>
+#include <linux/delay.h>
 
 #include <mach/hardware.h>
 #include <video/atmel_lcdc.h>
+#include <media/soc_camera.h>
+#include <media/atmel-isi.h>
 
 #include <asm/setup.h>
 #include <asm/mach-types.h>
@@ -187,6 +189,76 @@ static void __init ek_add_device_nand(void)
 
 
 /*
+ *  ISI
+ */
+static struct isi_platform_data __initdata isi_data = {
+	.frate			= ISI_CFG1_FRATE_CAPTURE_ALL,
+	.has_emb_sync		= 0,
+	.emb_crc_sync		= 0,
+	.hsync_act_low		= 0,
+	.vsync_act_low		= 0,
+	.pclk_act_falling	= 0,
+	/* to use codec and preview path simultaneously */
+	.full_mode		= 1,
+	.data_width_flags	= ISI_DATAWIDTH_8 | ISI_DATAWIDTH_10,
+	/* ISI_MCK is provided by programmable clock or external clock  */
+	.mck_hz			= 25000000,
+};
+
+
+/*
+ * soc-camera OV2640
+ */
+#if defined(CONFIG_SOC_CAMERA_OV2640) || \
+	defined(CONFIG_SOC_CAMERA_OV2640_MODULE)
+static unsigned long isi_camera_query_bus_param(struct soc_camera_link *link)
+{
+	/* ISI board for ek using default 8-bits connection */
+	return SOCAM_DATAWIDTH_8;
+}
+
+static int i2c_camera_power(struct device *dev, int on)
+{
+	/* enable or disable the camera */
+	pr_debug("%s: %s the camera\n", __func__, on ? "ENABLE" : "DISABLE");
+	at91_set_gpio_output(AT91_PIN_PD13, !on);
+
+	if (!on)
+		goto out;
+
+	/* If enabled, give a reset impulse */
+	at91_set_gpio_output(AT91_PIN_PD12, 0);
+	msleep(20);
+	at91_set_gpio_output(AT91_PIN_PD12, 1);
+	msleep(100);
+
+out:
+	return 0;
+}
+
+static struct i2c_board_info i2c_camera = {
+	I2C_BOARD_INFO("ov2640", 0x30),
+};
+
+static struct soc_camera_link iclink_ov2640 = {
+	.bus_id			= 0,
+	.board_info		= &i2c_camera,
+	.i2c_adapter_id		= 0,
+	.power			= i2c_camera_power,
+	.query_bus_param	= isi_camera_query_bus_param,
+};
+
+static struct platform_device isi_ov2640 = {
+	.name	= "soc-camera-pdrv",
+	.id	= 0,
+	.dev	= {
+		.platform_data = &iclink_ov2640,
+	},
+};
+#endif
+
+
+/*
  * LCD Controller
  */
 #if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
@@ -378,7 +450,12 @@ static struct gpio_led ek_pwm_led[] = {
 #endif
 };
 
-
+static struct platform_device *devices[] __initdata = {
+#if defined(CONFIG_SOC_CAMERA_OV2640) || \
+	defined(CONFIG_SOC_CAMERA_OV2640_MODULE)
+	&isi_ov2640,
+#endif
+};
 
 static void __init ek_board_init(void)
 {
@@ -400,6 +477,8 @@ static void __init ek_board_init(void)
 	ek_add_device_nand();
 	/* I2C */
 	at91_add_device_i2c(0, NULL, 0);
+	/* ISI, using programmable clock as ISI_MCK */
+	at91_add_device_isi(&isi_data, 1);
 	/* LCD Controller */
 	at91_add_device_lcdc(&ek_lcdc_data);
 	/* Touch Screen */
@@ -411,6 +490,8 @@ static void __init ek_board_init(void)
 	/* LEDs */
 	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
 	at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led));
+	/* Other platform devices */
+	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
 MACHINE_START(AT91SAM9M10G45EK, "Atmel AT91SAM9M10G45-EK")
-- 
1.6.3.3

^ permalink raw reply related

* [PATCH V2 4/4] ARM: at91/dma: DMA controller registering with DT support
From: Sergei Shtylyov @ 2011-10-11 11:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1318265021-4562-1-git-send-email-nicolas.ferre@atmel.com>

Hello.

On 10-10-2011 20:43, Nicolas Ferre wrote:

> Device tree support on at91sam9g45 family SoC. Only call
> platform_device_register() if no compatible dma-controller
> node is found in device tree.

> Signed-off-by: Nicolas Ferre<nicolas.ferre@atmel.com>
> ---
> V2: use compatible string to match device.

[...]

> diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
> index 9390ae6..2120055 100644
> --- a/arch/arm/mach-at91/at91sam9g45_devices.c
> +++ b/arch/arm/mach-at91/at91sam9g45_devices.c
> @@ -64,7 +64,13 @@ static struct platform_device at_hdmac_device = {
>
>   void __init at91_add_device_hdmac(void)
>   {
> -	platform_device_register(&at_hdmac_device);
> +	struct device_node *np = of_find_node_by_name(NULL, "dma-controller");
> +
> +	if (np&&  of_device_is_compatible(np, "atmel,at91sam9g45-dma")) {
> +		of_node_put(np);
> +	} else {
> +		platform_device_register(&at_hdmac_device);
> +	}

    {} not needed here, and checkpatch.pl should have protested.

WBR, Sergei

^ permalink raw reply

* [RFT/PATCH 7/7] arm: omap: smartreflex: micro-optimization for sanity check
From: Sergei Shtylyov @ 2011-10-11 11:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1318249579-4089-7-git-send-email-balbi@ti.com>

Hello.

On 10-10-2011 16:26, Felipe Balbi wrote:

> val&&  (val != 1) == val>  1

> Signed-off-by: Felipe Balbi<balbi@ti.com>
> ---
>   arch/arm/mach-omap2/smartreflex.c |    2 +-
>   1 files changed, 1 insertions(+), 1 deletions(-)

> diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
> index 7bdabfa..4b0d6a8 100644
> --- a/arch/arm/mach-omap2/smartreflex.c
> +++ b/arch/arm/mach-omap2/smartreflex.c
> @@ -866,7 +866,7 @@ static int omap_sr_autocomp_store(void *data, u64 val)
>   	}
>
>   	/* Sanity check */
> -	if (val&&  (val != 1)) {
> +	if (val>  1) {
>   		pr_warning("%s: Invalid argument %lld\n", __func__, val);

    The format specified should be "%llu"?

WBR, Sergei

^ permalink raw reply

* [RFT/PATCH 6/7] arm: omap: smartreflex: fix IRQ handling bug
From: Sergei Shtylyov @ 2011-10-11 11:23 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1318249579-4089-6-git-send-email-balbi@ti.com>

Hello.

On 10-10-2011 16:26, Felipe Balbi wrote:

> fix a bug which has been on this driver since
> it was added by the original commit 984aa6db

    Please also specify that commit's summary in parens.

> which would never clear IRQSTATUS bits.

> Signed-off-by: Felipe Balbi <balbi@ti.com>

WBR, Sergei

^ permalink raw reply

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
From: Richard Zhao @ 2011-10-11 11:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1316730422-20027-2-git-send-email-mturquette@ti.com>

On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, and a set of clock operations. Different clock
> implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> The interface is split into two halves:
> 
>  * struct clk, which is the generic-device-driver interface. This
>    provides a set of functions which drivers may use to request
>    enable/disable, query or manipulate in a hardware-independent manner.
> 
>  * struct clk_hw and struct clk_hw_ops, which is the hardware-specific
>    interface. Clock drivers implement the ops, which allow the core
>    clock code to implement the generic 'struct clk' API.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.
> 
> Platforms can enable the generic struct clock through
> CONFIG_GENERIC_CLK. In this case, the clock infrastructure consists of a
> common, opaque struct clk, and a set of clock operations (defined per
> type of clock):
> 
>   struct clk_hw_ops {
>   	int		(*prepare)(struct clk_hw *);
>   	void		(*unprepare)(struct clk_hw *);
>   	int		(*enable)(struct clk_hw *);
>   	void		(*disable)(struct clk_hw *);
>   	unsigned long	(*recalc_rate)(struct clk_hw *);
>   	int		(*set_rate)(struct clk_hw *,
>   					unsigned long, unsigned long *);
>   	long		(*round_rate)(struct clk_hw *, unsigned long);
>   	int		(*set_parent)(struct clk_hw *, struct clk *);
>   	struct clk *	(*get_parent)(struct clk_hw *);
>   };
> 
> Platform clock code can register a clock through clk_register, passing a
> set of operations, and a pointer to hardware-specific data:
> 
>   struct clk_hw_foo {
>   	struct clk_hw clk;
>   	void __iomem *enable_reg;
>   };
> 
>   #define to_clk_foo(c) offsetof(c, clk_hw_foo, clk)
> 
>   static int clk_foo_enable(struct clk_hw *clk)
>   {
>   	struct clk_foo *foo = to_clk_foo(clk);
>   	raw_writeb(foo->enable_reg, 1);
>   	return 0;
>   }
> 
>   struct clk_hw_ops clk_foo_ops = {
>   	.enable = clk_foo_enable,
>   };
> 
> And in the platform initialisation code:
> 
>   struct clk_foo my_clk_foo;
> 
>   void init_clocks(void)
>   {
>   	my_clk_foo.enable_reg = ioremap(...);
> 
>   	clk_register(&clk_foo_ops, &my_clk_foo, NULL);
>   }
> 
> Changes from Thomas Gleixner <tglx@linutronix.de>.
> 
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt <benh@kernel.crashing.org>.
> 
> TODO:
> 
>  * We don't keep any internal reference to the clock topology at present.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Mike Turquette <mturquette@ti.com>
> ---
> Changes since v1:
> Create a dummy clk_unregister and prototype/document it and clk_register
> Constify struct clk_hw_ops
> Remove spinlock.h header, include kernel.h
> Use EOPNOTSUPP instead of ENOTSUPP
> Add might_sleep to clk_prepare/clk_unprepare stubs
> Properly init children hlist and child_node
> Whitespace and typo fixes
> 
>  drivers/clk/Kconfig  |    3 +
>  drivers/clk/Makefile |    1 +
>  drivers/clk/clk.c    |  232 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/clkdev.c |    7 ++
>  include/linux/clk.h  |  140 +++++++++++++++++++++++++++---
>  5 files changed, 371 insertions(+), 12 deletions(-)
>  create mode 100644 drivers/clk/clk.c
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 3530927..c53ed59 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -5,3 +5,6 @@ config CLKDEV_LOOKUP
>  
>  config HAVE_MACH_CLKDEV
>  	bool
> +
> +config GENERIC_CLK
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 07613fa..570d5b9 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,2 +1,3 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> +obj-$(CONFIG_GENERIC_CLK)	+= clk.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..1cd7315
> --- /dev/null
> +++ b/drivers/clk/clk.c
> @@ -0,0 +1,232 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +
> +struct clk {
> +	const char		*name;
> +	const struct clk_hw_ops	*ops;
> +	struct clk_hw		*hw;
> +	unsigned int		enable_count;
> +	unsigned int		prepare_count;
> +	struct clk		*parent;
> +	unsigned long		rate;
> +};
> +
> +static DEFINE_SPINLOCK(enable_lock);
> +static DEFINE_MUTEX(prepare_lock);
> +
> +static void __clk_unprepare(struct clk *clk)
> +{
> +	if (!clk)
> +		return;
> +
> +	if (WARN_ON(clk->prepare_count == 0))
> +		return;
> +
> +	if (--clk->prepare_count > 0)
> +		return;
> +
> +	WARN_ON(clk->enable_count > 0);
> +
> +	if (clk->ops->unprepare)
> +		clk->ops->unprepare(clk->hw);
> +
> +	__clk_unprepare(clk->parent);
> +}
> +
> +void clk_unprepare(struct clk *clk)
> +{
> +	mutex_lock(&prepare_lock);
> +	__clk_unprepare(clk);
> +	mutex_unlock(&prepare_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_unprepare);
> +
> +static int __clk_prepare(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	if (!clk)
> +		return 0;
> +
> +	if (clk->prepare_count == 0) {
> +		ret = __clk_prepare(clk->parent);
> +		if (ret)
> +			return ret;
> +
> +		if (clk->ops->prepare) {
> +			ret = clk->ops->prepare(clk->hw);
> +			if (ret) {
> +				__clk_unprepare(clk->parent);
> +				return ret;
> +			}
> +		}
> +	}
> +
> +	clk->prepare_count++;
> +
> +	return 0;
> +}
> +
> +int clk_prepare(struct clk *clk)
> +{
> +	int ret;
> +
> +	mutex_lock(&prepare_lock);
> +	ret = __clk_prepare(clk);
> +	mutex_unlock(&prepare_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_prepare);
> +
> +static void __clk_disable(struct clk *clk)
> +{
> +	if (!clk)
> +		return;
> +
> +	if (WARN_ON(clk->enable_count == 0))
> +		return;
> +
> +	if (--clk->enable_count > 0)
> +		return;
> +
> +	if (clk->ops->disable)
> +		clk->ops->disable(clk->hw);
> +	__clk_disable(clk->parent);
> +}
> +
> +void clk_disable(struct clk *clk)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&enable_lock, flags);
> +	__clk_disable(clk);
> +	spin_unlock_irqrestore(&enable_lock, flags);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable);
> +
> +static int __clk_enable(struct clk *clk)
> +{
> +	int ret;
> +
> +	if (!clk)
> +		return 0;
> +
> +	if (WARN_ON(clk->prepare_count == 0))
> +		return -ESHUTDOWN;
> +
> +
> +	if (clk->enable_count == 0) {
> +		ret = __clk_enable(clk->parent);
> +		if (ret)
> +			return ret;
> +
> +		if (clk->ops->enable) {
> +			ret = clk->ops->enable(clk->hw);
> +			if (ret) {
> +				__clk_disable(clk->parent);
> +				return ret;
> +			}
> +		}
> +	}
> +
> +	clk->enable_count++;
> +	return 0;
> +}
> +
> +int clk_enable(struct clk *clk)
> +{
> +	unsigned long flags;
> +	int ret;
> +
> +	spin_lock_irqsave(&enable_lock, flags);
> +	ret = __clk_enable(clk);
> +	spin_unlock_irqrestore(&enable_lock, flags);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_enable);
> +
> +unsigned long clk_get_rate(struct clk *clk)
> +{
> +	if (!clk)
> +		return 0;
> +	return clk->rate;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_rate);
> +
> +long clk_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk && clk->ops->round_rate)
> +		return clk->ops->round_rate(clk->hw, rate);
> +	return rate;
> +}
> +EXPORT_SYMBOL_GPL(clk_round_rate);
> +
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	/* not yet implemented */
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_rate);
> +
> +struct clk *clk_get_parent(struct clk *clk)
> +{
> +	if (!clk)
> +		return NULL;
> +
> +	return clk->parent;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_parent);
> +
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	/* not yet implemented */
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_parent);
> +
> +struct clk *clk_register(const struct clk_hw_ops *ops, struct clk_hw *hw,
> +		const char *name)
> +{
> +	struct clk *clk;
> +
> +	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
> +	if (!clk)
> +		return NULL;
> +
> +	INIT_HLIST_HEAD(&clk->children);
> +	INIT_HLIST_NODE(&clk->child_node);
> +
> +	clk->name = name;
> +	clk->ops = ops;
> +	clk->hw = hw;
> +	hw->clk = clk;
> +
> +	/* Query the hardware for parent and initial rate */
> +
> +	if (clk->ops->get_parent)
> +		/* We don't to lock against prepare/enable here, as
> +		 * the clock is not yet accessible from anywhere */
> +		clk->parent = clk->ops->get_parent(clk->hw);
> +
> +	if (clk->ops->recalc_rate)
> +		clk->rate = clk->ops->recalc_rate(clk->hw);
Why not set it to parent's rate if recalc_rate is NULL?
> +
> +
> +	return clk;
> +}
> +EXPORT_SYMBOL_GPL(clk_register);
> diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
> index 6db161f..e2a9719 100644
> --- a/drivers/clk/clkdev.c
> +++ b/drivers/clk/clkdev.c
> @@ -23,6 +23,13 @@
>  static LIST_HEAD(clocks);
>  static DEFINE_MUTEX(clocks_mutex);
>  
> +/* For USE_COMMON_STRUCT_CLK, these are provided in clk.c, but not exported
> + * through other headers; we don't want them used anywhere but here. */
> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
> +extern int __clk_get(struct clk *clk);
> +extern void __clk_put(struct clk *clk);
> +#endif
> +
>  /*
>   * Find the correct struct clk for the device and connection ID.
>   * We do slightly fuzzy matching here:
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..d6ae10b 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -3,6 +3,7 @@
>   *
>   *  Copyright (C) 2004 ARM Limited.
>   *  Written by Deep Blue Solutions Limited.
> + *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License version 2 as
> @@ -11,17 +12,137 @@
>  #ifndef __LINUX_CLK_H
>  #define __LINUX_CLK_H
>  
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +
>  struct device;
>  
> -/*
> - * The base API.
> +struct clk;
> +
> +#ifdef CONFIG_GENERIC_CLK
> +
> +struct clk_hw {
> +	struct clk *clk;
> +};
> +
> +/**
> + * struct clk_hw_ops -  Callback operations for hardware clocks; these are to
> + * be provided by the clock implementation, and will be called by drivers
> + * through the clk_* API.
> + *
> + * @prepare:	Prepare the clock for enabling. This must not return until
> + *		the clock is fully prepared, and it's safe to call clk_enable.
> + *		This callback is intended to allow clock implementations to
> + *		do any initialisation that may sleep. Called with
> + *		prepare_lock held.
> + *
> + * @unprepare:	Release the clock from its prepared state. This will typically
> + *		undo any work done in the @prepare callback. Called with
> + *		prepare_lock held.
> + *
> + * @enable:	Enable the clock atomically. This must not return until the
> + *		clock is generating a valid clock signal, usable by consumer
> + *		devices. Called with enable_lock held. This function must not
> + *		sleep.
> + *
> + * @disable:	Disable the clock atomically. Called with enable_lock held.
> + *		This function must not sleep.
> + *
> + * @recalc_rate	Recalculate the rate of this clock, by quering hardware
> + *		and/or the clock's parent. Called with the global clock mutex
> + *		held. Optional, but recommended - if this op is not set,
> + *		clk_get_rate will return 0.
If a clock don't have any divider, recalc_rate may be NULL. In such case,
clk_get_rate should return parent's rate.

Thanks
Richard
> + *
> + * @get_parent	Query the parent of this clock; for clocks with multiple
> + *		possible parents, query the hardware for the current
> + *		parent. Currently only called when the clock is first
> + *		registered.
> + *
> + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
> + * implementations to split any work between atomic (enable) and sleepable
> + * (prepare) contexts.  If a clock requires sleeping code to be turned on, this
> + * should be done in clk_prepare. Switching that will not sleep should be done
> + * in clk_enable.
> + *
> + * Typically, drivers will call clk_prepare when a clock may be needed later
> + * (eg. when a device is opened), and clk_enable when the clock is actually
> + * required (eg. from an interrupt). Note that clk_prepare *must* have been
> + * called before clk_enable.
>   */
> +struct clk_hw_ops {
> +	int		(*prepare)(struct clk_hw *);
> +	void		(*unprepare)(struct clk_hw *);
> +	int		(*enable)(struct clk_hw *);
> +	void		(*disable)(struct clk_hw *);
> +	unsigned long	(*recalc_rate)(struct clk_hw *);
> +	long		(*round_rate)(struct clk_hw *, unsigned long);
> +	struct clk *	(*get_parent)(struct clk_hw *);
> +};
>  
> +/**
> + * clk_prepare - prepare clock for atomic enabling.
> + *
> + * @clk: The clock to prepare
> + *
> + * Do any possibly sleeping initialisation on @clk, allowing the clock to be
> + * later enabled atomically (via clk_enable). This function may sleep.
> + */
> +int clk_prepare(struct clk *clk);
> +
> +/**
> + * clk_unprepare - release clock from prepared state
> + *
> + * @clk: The clock to release
> + *
> + * Do any (possibly sleeping) cleanup on clk. This function may sleep.
> + */
> +void clk_unprepare(struct clk *clk);
> +
> +/**
> + * clk_register - register and initialize a new clock
> + *
> + * @ops: ops for the new clock
> + * @hw: struct clk_hw to be passed to the ops of the new clock
> + * @name: name to use for the new clock
> + *
> + * Register a new clock with the clk subsystem.  Returns either a
> + * struct clk for the new clock or a NULL pointer.
> + */
> +struct clk *clk_register(const struct clk_hw_ops *ops, struct clk_hw *hw,
> +			 const char *name);
> +
> +/**
> + * clk_unregister - remove a clock
> + *
> + * @clk: clock to unregister
> + *
> + * Remove a clock from the clk subsystem.  This is currently not
> + * implemented but is provided to allow unregistration code to be
> + * written in drivers ready for use when an implementation is
> + * provided.
> + */
> +static inline int clk_unregister(struct clk *clk)
> +{
> +	return -EOPNOTSUPP;
> +}
> +
> +#else /* !CONFIG_GENERIC_CLK */
>  
>  /*
> - * struct clk - an machine class defined object / cookie.
> + * For !CONFIG_GENERIC_CLK, we don't enforce any atomicity
> + * requirements for clk_enable/clk_disable, so the prepare and unprepare
> + * functions are no-ops
>   */
> -struct clk;
> +static inline int clk_prepare(struct clk *clk) {
> +	might_sleep();
> +	return 0;
> +}
> +
> +static inline void clk_unprepare(struct clk *clk) {
> +	might_sleep();
> +}
> +
> +#endif /* !CONFIG_GENERIC_CLK */
>  
>  /**
>   * clk_get - lookup and obtain a reference to a clock producer.
> @@ -67,6 +188,7 @@ void clk_disable(struct clk *clk);
>  /**
>   * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
>   *		  This is only valid once the clock source has been enabled.
> + *		  Returns zero if the clock rate is unknown.
>   * @clk: clock source
>   */
>  unsigned long clk_get_rate(struct clk *clk);
> @@ -83,12 +205,6 @@ unsigned long clk_get_rate(struct clk *clk);
>   */
>  void clk_put(struct clk *clk);
>  
> -
> -/*
> - * The remaining APIs are optional for machine class support.
> - */
> -
> -
>  /**
>   * clk_round_rate - adjust a rate to the exact rate a clock can provide
>   * @clk: clock source
> @@ -97,7 +213,7 @@ void clk_put(struct clk *clk);
>   * Returns rounded clock rate in Hz, or negative errno.
>   */
>  long clk_round_rate(struct clk *clk, unsigned long rate);
> - 
> +
>  /**
>   * clk_set_rate - set the clock rate for a clock source
>   * @clk: clock source
> @@ -106,7 +222,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate);
>   * Returns success (0) or negative errno.
>   */
>  int clk_set_rate(struct clk *clk, unsigned long rate);
> - 
> +
>  /**
>   * clk_set_parent - set the parent clock source for this clock
>   * @clk: clock source
> -- 
> 1.7.4.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

^ permalink raw reply

* [Linaro-mm-sig] [PATCHv16 0/9] Contiguous Memory Allocator
From: Maxime Coquelin @ 2011-10-11 11:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <00b301cc8803$93b5b3e0$bb211ba0$%szyprowski@samsung.com>

On 10/11/2011 12:50 PM, Marek Szyprowski wrote:
> Hello,
>
> On Tuesday, October 11, 2011 9:30 AM Maxime Coquelin wrote:
>
>> On 10/11/2011 09:17 AM, Marek Szyprowski wrote:
>>> On Monday, October 10, 2011 2:08 PM Maxime Coquelin wrote:
>>>
>>>        During our stress tests, we encountered some problems :
>>>
>>>        1) Contiguous allocation lockup:
>>>            When system RAM is full of Anon pages, if we try to allocate a
>>> contiguous buffer greater than the min_free value, we face a
>>> dma_alloc_from_contiguous lockup.
>>>            The expected result would be dma_alloc_from_contiguous() to fail.
>>>            The problem is reproduced systematically on our side.
>>> Thanks for the report. Do you use Android's lowmemorykiller? I haven't
>>> tested CMA on Android kernel yet. I have no idea how it will interfere
>>> with Android patches.
>>>
>> The software used for this test (v16) is a generic 3.0 Kernel and a
>> minimal filesystem using Busybox.
> I'm really surprised. Could you elaborate a bit how to trigger this issue?

At system startup, I drop caches (sync && echo 3 > 
/proc/sys/vm/drop_caches) and check how much memory is free.
For example, in my case, only 15MB is used on the 270MB available on the 
system, so I got 255MB of free memory. Note that the min_free is 4MB in 
my case.
In userspace, I allocate 230MB using malloc(), the free memory is now 25MB.
Finaly, I ask for a contiguous allocation of 64MB using CMA, the result 
is a lockup in dma_alloc_from_contiguous().

> I've did several tests and I never get a lockup. Allocation failed from time
> to time though.
When it succeed, what is the behaviour on your side? Is the OOM triggered?

Regards,
Maxime

^ permalink raw reply

* [PATCH v2 6/6] OMAP4: Clock: Correct the name of SLIMBUS interface clocks
From: Cousson, Benoit @ 2011-10-11 11:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4E9364E7.80708@ti.com>

On 10/10/2011 11:34 PM, Hunter, Jon wrote:
> Hi Benoit,
> 
> On 10/10/2011 4:54, Cousson, Benoit wrote:
>> Hi Jon,
>>
>> On 10/8/2011 12:46 AM, Hunter, Jon wrote:
>>> Hi Benoit,
>>>
>>> On 10/7/2011 3:23, Cousson, Benoit wrote:
>>>> Hi Paul&  Jon,
>>>>
>>>> On 10/7/2011 3:42 AM, Paul Walmsley wrote:
>>>>> + Beno?t
>>>>>
>>>>> On Fri, 16 Sep 2011, Jon Hunter wrote:
>>>>>
>>>>>> From: Jon Hunter<jon-hunter@ti.com>
>>>>>>
>>>>>> Currently the interface clocks for the two SLIMBUS peripherals are
>>>>>> named slimbus1_fck and slimbus2_fck. Rename these clocks to be
>>>>>> slimbus1_ick and slimbus2_ick so it is clear that these are
>>>>>> interface clocks and not functional clocks.
>>>>>>
>>>>>> Signed-off-by: Jon Hunter<jon-hunter@ti.com>
>>>>>
>>>>> This one, I don't quite understand. We should probably be removing
>>>>> these
>>>>> MODULEMODE-only clocks from the OMAP4 tree, and using their parent
>>>>> clock
>>>>> as the main_clk. That would be a good cleanup for 3.3...
>>>>
>>>> Yes, but in order to remove that from the clock data we must ensure that
>>>> the hwmod entry is there.
>>>> I kept a lot of legacy MODULEMODE clocks just because of missing hwmod /
>>>> runtime_pm adaptation on some drivers.
>>>>
>>>> In the case of slimbus, there is no main_clk but a bunch of optional
>>>> clocks. It looks similar to the DSS case. So we should not use the
>>>> parent clock as a main_clk.
>>>>
>>>> We should probably promote one of the opt_clk as the main_clk. The
>>>> slimbus_clk seems to be the good candidate for both instances.
>>>>
>>>> static struct omap_hwmod_opt_clk slimbus1_opt_clks[] = {
>>>> { .role = "fclk_1", .clk = "slimbus1_fclk_1" },
>>>> { .role = "fclk_0", .clk = "slimbus1_fclk_0" },
>>>> { .role = "fclk_2", .clk = "slimbus1_fclk_2" },
>>>> { .role = "slimbus_clk", .clk = "slimbus1_slimbus_clk" },
>>>> };
>>>>
>>>> static struct omap_hwmod_opt_clk slimbus2_opt_clks[] = {
>>>> { .role = "fclk_1", .clk = "slimbus2_fclk_1" },
>>>> { .role = "fclk_0", .clk = "slimbus2_fclk_0" },
>>>> { .role = "slimbus_clk", .clk = "slimbus2_slimbus_clk" },
>>>> };
>>>>
>>>> Jon,
>>>> Do you know if that one is indeed mandatory to use the slimbus IP?
>>>
>>> Sorry, are you asking about the clocks I was re-naming or the
>>> slimbus_clk you are referring to above?
>>
>> The clocks you are renaming should not exist at all, so I was referring
>> to the real clocks that are all listed as optional clocks.
> 
> These clocks are the interface clocks enabled via the module-mode. So
> you are saying you want to remove the interface clocks from the list of
> clocks?

Yes or No, dependeing of which clock you are talking about.
The real interface clock is already handled thanks to the ocp_if structure.

/* l4_abe -> slimbus1 */
static struct omap_hwmod_ocp_if omap44xx_l4_abe__slimbus1 = {
       .master         = &omap44xx_l4_abe_hwmod,
       .slave          = &omap44xx_slimbus1_hwmod,
       .clk            = "ocp_abe_iclk",
       .addr           = omap44xx_slimbus1_addrs,
       .user           = OCP_USER_MPU,
};

And since the modulemodule is now handled by the hwmod core thanks to that:

       .prcm = {
               .omap4 = {
                       .clkctrl_offs = OMAP4_CM1_ABE_SLIMBUS_CLKCTRL_OFFSET,
                       .context_offs = OMAP4_RM_ABE_SLIMBUS_CONTEXT_OFFSET,
                       .modulemode   = MODULEMODE_SWCTRL,
               },
       },

There is no need to create a fake leaf clock to handle the module using the clock fmwk.


So we can now remove these two clock nodes from the clock44xx_data.c file:

static struct clk slimbus1_fck = {
	.name		= "slimbus1_fck",
	.ops		= &clkops_omap2_dflt,
	.enable_reg	= OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
	.clkdm_name	= "abe_clkdm",
	.parent		= &ocp_abe_iclk,
	.recalc		= &followparent_recalc,
};

static struct clk slimbus2_fck = {
	.name		= "slimbus2_fck",
	.ops		= &clkops_omap2_dflt,
	.enable_reg	= OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
	.clkdm_name	= "l4_per_clkdm",
	.parent		= &l4_div_ck,
	.recalc		= &followparent_recalc,
};

>> Usually we do need to have a main_clk in order to access the IP
>> registers (at least the sysconfig). But for some IPs, the iclk can be
>> enough.
>> If the interface clock is enough, then potentially that main clock is
>> not mandatory. But if one functional clock is mandatory, then we have to
>> figured out which one from the various optional functional clocks can be
>> used as the main_clk.
>>
>>> Looking at the clock tree tool, the slimbus_clk is the actual external
>>> slimbus clock that can be generated by OMAP or by an external device.
>>>
>>> The TRM states ...
>>>
>>> "Most of the SLIMbus module runs off two main clocks: the L4 interface
>>> clock for the data input and output registers, and the control and
>>> status control registers; and the SLIMbus clock, taken from the serial
>>> interface (CLK line) for the SLIMbus-side logic.
>>>
>>> The SLIMbus controller operates as clock source component (active
>>> framer), which drives the SLIMbus clock line CLK, or as clock receiver
>>> component, which gets its clock from the same CLK line."
>>>
>>> So, if you are operating as the clock source component on the bus then
>>> one of the optional clocks to drive the peripheral logic and if you are
>>> the clock receiver then you use slimbus_clk.
>>
>> OK, so clearly, the slimbus_clk cannot be a main_clk. We have to check
>> if the registers can be accessed only with the iclk.
> 
> I ran a quick test. If I just set the module mode to 0x2 (enabled), then
> I can access the registers. So no need to turn on any of the
> optional/functional clocks just the iclk.

That's good, so it looks like you will not have to populate the main_clk at all.

Regards,
Benoit

^ permalink raw reply

* [PATCH] ARM: SAMSUNG: s3c-dma-ops needs export.h for EXPORT_SYMBOL
From: Kukjin Kim @ 2011-10-11 11:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317961214.16109.1.camel@phoenix>

Axel Lin wrote:
> 
> Fix below build warning:
>   CC      arch/arm/plat-samsung/s3c-dma-ops.o
> arch/arm/plat-samsung/s3c-dma-ops.c:130: warning: data definition has no type or
> storage class
> arch/arm/plat-samsung/s3c-dma-ops.c:130: warning: type defaults to 'int' in
> declaration of 'EXPORT_SYMBOL'
> arch/arm/plat-samsung/s3c-dma-ops.c:130: warning: parameter names (without
> types) in function declaration
> 
> And fix the build error:
> ERROR: "s3c_dma_get_ops" [drivers/spi/spi-s3c64xx.ko] undefined!
> make[1]: *** [__modpost] Error 1
> make: *** [modules] Error 2
> 
> Signed-off-by: Axel Lin <axel.lin@gmail.com>
> ---
> This can be reproduced by "make s3c6400_defconfig;make" on linux-next
> 20111006.
>  arch/arm/plat-samsung/s3c-dma-ops.c |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/plat-samsung/s3c-dma-ops.c b/arch/arm/plat-samsung/s3c-
> dma-ops.c
> index 582333c..7814949 100644
> --- a/arch/arm/plat-samsung/s3c-dma-ops.c
> +++ b/arch/arm/plat-samsung/s3c-dma-ops.c
> @@ -14,6 +14,7 @@
>  #include <linux/errno.h>
>  #include <linux/slab.h>
>  #include <linux/types.h>
> +#include <linux/export.h>
> 
>  #include <mach/dma.h>
> 
> --
> 1.7.4.1
> 
OK, will apply.

BTW, I don't know why the build error/warning was not happened in my tree with s3c6400_defconfig. Probably other file having it?...

Anyway, thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

^ 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