* [PATCH v4 1/3] clocksource: timer-keystone: introduce clocksource driver for Keystone
From: Santosh Shilimkar @ 2014-02-04 22:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.02.1402042113270.24986@ionos.tec.linutronix.de>
On Tuesday 04 February 2014 03:17 PM, Thomas Gleixner wrote:
> On Tue, 4 Feb 2014, Ivan Khoronzhuk wrote:
>
> Please do not top post.
>
>> It was so in v1. But it was decided to use explicit memory barriers,
>> because we're always sure the memory barriers are there and that
>> they're properly documented. Also in this case I don't need to add
>> keystone readl/writel relaxed function variants and to use mixed calls of
>> writel/writel_relaxed functions.
>>
>> See:
>> http://www.spinics.net/lists/arm-kernel/msg294941.html
>
> Fair enough, but we want a proper explanation for explicit barriers in
> the code and not in some random discussion of patch version X on some
> random mailing list.
>
> Aside of that it should be iowmb(), but I might miss something ...
>
Agree. __iowmb() seems to be more appropriate.
Regards,
Santosh
^ permalink raw reply
* [PATCH] ARM: spinlock: ensure we have a compiler barrier before sev
From: Christoffer Dall @ 2014-02-04 22:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391516926-14493-1-git-send-email-will.deacon@arm.com>
On Tue, Feb 04, 2014 at 12:28:46PM +0000, Will Deacon wrote:
> When unlocking a spinlock, we require the following, strictly ordered
> sequence of events:
>
> <barrier> /* dmb */
> <unlock>
> <barrier> /* dsb */
> <sev>
>
> Whilst the code does indeed reflect this in terms of the architecture,
> the final <barrier> + <sev> have been contracted into a single inline
> asm without a "memory" clobber, therefore the compiler is at liberty to
> reorder the unlock to the end of the above sequence. In such a case,
> a waiting CPU may be woken up before the lock has been unlocked, leading
> to extremely poor performance.
>
> This patch reworks the dsb_sev() function to make use of the dsb()
> macro and ensure ordering against the unlock.
>
> Cc: <stable@vger.kernel.org>
> Reported-by: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Will Deacon <will.deacon@arm.com>
FWIW: Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
^ permalink raw reply
* Weird sched_clock behaviour during boot with -rc1
From: Stephen Boyd @ 2014-02-04 22:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <52F1518B.9010109@linaro.org>
On 02/04, John Stultz wrote:
> On 02/04/2014 10:36 AM, Will Deacon wrote:
> > Hi guys,
> >
> > Booting -rc1 on my TC2 gives the following strange entries in the dmesg:
> >
> >
> > Uncompressing Linux... done, booting the kernel.
> > [ 0.000000] Booting Linux on physical CPU 0x0
> >
> > [...]
> >
> > [ 0.000000] HighMem zone: 329728 pages, LIFO batch:31
> > [ 7.789662] sched_clock: 32 bits at 24MHz, resolution 41ns, wraps every 178956969942ns
> > [ 0.000129] PERCPU: Embedded 9 pages/cpu @ee7bd000 s12800 r8192 d15872 u36864
> >
> > [...]
> >
> > [ 0.868297] NR_IRQS:16 nr_irqs:16 16
> > [ 0.886350] Architected cp15 timer(s) running at 24.00MHz (phys).
> > [ 2915.164998] sched_clock: 56 bits at 24MHz, resolution 41ns, wraps every 2863311519744ns
> > [ 0.000002] Switching to timer-based delay loop
> > [ 0.014249] Console: colour dummy device 80x30
> >
> >
> > so it looks like something whacky goes on during sched_clock registration.
> > Sure enough, we're doing a pr_info in-between updating cs.* and calling
> > update_sched_clock(), so moving the print sorts things out (diff below).
>
> Yea... we have to be particularly careful with sched_clock to avoid
> locks since we don't want to deadlock, but in this case
> sched_clock_register is a little too relaxed here.
>
> Stephen: Would it make sense to set cd.suspended = true at the top of
> the registration? That should block any sched_clock calls from getting
> half-updated data, but still allow the sched_clock_update function to work.
>
That would work, but why can't we just hold the write seqlock
during the registration? We would need to make a lockeless
version of update_sched_clock() but that doesn't look too hard.
It might actually turn out nicer because we call
update_sched_clock() here just to set the epoch_cyc but we have
to reset the epoch_ns back to 0 to start the count off right.
How about this? The only concern is calling read_sched_clock()
inside the seqlock, but I don't think that's a concern and if it
is we can call it outside the lock at the beginning of this
function.
----8<----
diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c
index 0abb36464281..ae8f10a02c32 100644
--- a/kernel/time/sched_clock.c
+++ b/kernel/time/sched_clock.c
@@ -124,6 +124,7 @@ void __init sched_clock_register(u64 (*read)(void), int bits,
return;
WARN_ON(!irqs_disabled());
+ raw_write_seqcount_begin(&cd.seq);
read_sched_clock = read;
sched_clock_mask = CLOCKSOURCE_MASK(bits);
cd.rate = rate;
@@ -147,15 +148,16 @@ void __init sched_clock_register(u64 (*read)(void), int bits,
/* calculate the ns resolution of this counter */
res = cyc_to_ns(1ULL, cd.mult, cd.shift);
- pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lluns\n",
- bits, r, r_unit, res, wrap);
-
- update_sched_clock();
/*
* Ensure that sched_clock() starts off at 0ns
*/
cd.epoch_ns = 0;
+ cd.epoch_cyc = read_sched_clock();
+ raw_write_seqcount_end(&cd.seq);
+
+ pr_info("sched_clock: %u bits@%lu%cHz, resolution %lluns, wraps every %lluns\n",
+ bits, r, r_unit, res, wrap);
/* Enable IRQ time accounting if we have a fast enough sched_clock */
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply related
* [PATCH] dma: mv_xor: Silence a bunch of LPAE-related warnings
From: Olof Johansson @ 2014-02-04 21:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAPcyv4jwwRT_+c-yDycgY0d79nByvAVWH6waFWeodE9yi=7CDg@mail.gmail.com>
On Tue, Feb 4, 2014 at 10:57 AM, Dan Williams <dan.j.williams@intel.com> wrote:
> On Tue, Feb 4, 2014 at 10:30 AM, Olof Johansson <olof@lixom.net> wrote:
>> On Tue, Feb 4, 2014 at 9:00 AM, Jason Cooper <jason@lakedaemon.net> wrote:
>>> On Tue, Feb 04, 2014 at 10:53:29AM +0530, Vinod Koul wrote:
>>>> On Mon, Feb 03, 2014 at 05:13:23PM -0800, Olof Johansson wrote:
>>>> > Enabling some of the mvebu platforms in the multiplatform config for ARM
>>>> > enabled these drivers, which also triggered a bunch of warnings when LPAE
>>>> > is enabled (thus making phys_addr_t 64-bit).
>>>> >
>>>> > Most changes are switching printk formats, but also a bit of changes to what
>>>> > used to be array-based pointer arithmetic that could just be done with the
>>>> > address types instead.
>>>> >
>>>> > The warnings were:
>>>> >
>>>> > drivers/dma/mv_xor.c: In function 'mv_xor_tx_submit':
>>>> > drivers/dma/mv_xor.c:500:3: warning: format '%x' expects argument of type
>>>> > 'unsigned int', but argument 4 has type 'dma_addr_t' [-Wformat]
>>>> > drivers/dma/mv_xor.c: In function 'mv_xor_alloc_chan_resources':
>>>> > drivers/dma/mv_xor.c:553:13: warning: cast to pointer from integer of
>>>> > different size [-Wint-to-pointer-cast]
>>>> > drivers/dma/mv_xor.c:555:4: warning: cast from pointer to integer of
>>>> > different size [-Wpointer-to-int-cast]
>>>> > drivers/dma/mv_xor.c: In function 'mv_xor_prep_dma_memcpy':
>>>> > drivers/dma/mv_xor.c:584:2: warning: format '%x' expects argument of type
>>>> > 'unsigned int', but argument 5 has type 'dma_addr_t' [-Wformat]
>>>> > drivers/dma/mv_xor.c:584:2: warning: format '%x' expects argument of type
>>>> > 'unsigned int', but argument 6 has type 'dma_addr_t' [-Wformat]
>>>> > drivers/dma/mv_xor.c: In function 'mv_xor_prep_dma_xor':
>>>> > drivers/dma/mv_xor.c:628:2: warning: format '%u' expects argument of type
>>>> > 'unsigned int', but argument 7 has type 'dma_addr_t' [-Wformat]
>>>> >
>>>> > Signed-off-by: Olof Johansson <olof@lixom.net>
>>>> Acked-by: Vinod Koul <vinod.koul@intel.com>
>>>
>>> Olof, would you like me to queue it up? Or do you want to take it
>>> directly?
>>>
>>> Acked-by: Jason Cooper <jason@lakedaemon.net>
>>
>> I'm confused. I sent the patch to the drivers/dma maintainers and they
>> just acked it without asking me to pick it up myself.
>>
>> Vinod, did you ack it for me to pick it up, or for some other reason?
>> If you don't want to take it through your tree I'll be happy to take
>> it through arm-soc, just looking to clarify.
>>
>> (Jason, I can apply it directly)
>
> Vinod will correct me if I am wrong, but I take his acks to mean "yup,
> take it through your tree".
Ok, thanks, we'll do that then.
-Olof
^ permalink raw reply
* Extending OPP bindings
From: Nishanth Menon @ 2014-02-04 21:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140204201122.GB22609@sirena.org.uk>
On 02/04/2014 02:11 PM, Mark Brown wrote:
> On Tue, Feb 04, 2014 at 01:28:20PM -0600, Nishanth Menon wrote:
>> On 02/04/2014 12:22 PM, Mark Brown wrote:
>
>>> You're assuming that the frequency is a unique key here. That may not
>>> be the case, for example two OPPs might have the same CPU clock
>>> (assuming that's the frequency you're referring to) but different bus
>>> clocking and of course the CPUs or CPU clusters might be individually
>>> scalable (this is common in big.LITTLE designs I think).
>
>> Which is why OPPs are maintained per device, bus OPPs belong to bus
>> device (in TI terminology, we'd be talking of cross domain dependency
>> here for maintaining asynchronous bridge timing closure constraints -
>> but ofcourse, other SoCs may or maynot have such constraints). For
>> scaling bus frequency, we already have infrastructure in place - clock
>> notifiers - discussion of using that is much deeper topic of it's own.
>
>> for each processor that is uniquely transitioning, we'd have it's own
>> sets of OPPs - the correct representation of the device node is the
>> key there.
>
> I've seen some SoCs characterised over the whole device rather than with
> individual parts of the SoC done separately.
>
Fair enough - however, the data characterized will imply individual
processor/bus specific tuples/parameters - the specific parameters
might be very unique for SoC, but we have ability to abstract it per
SoC already.
--
Regards,
Nishanth Menon
^ permalink raw reply
* [GIT PULL] irqchip: dove: drivers for v3.14
From: Thomas Gleixner @ 2014-02-04 21:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140204211219.GK8533@titan.lakedaemon.net>
On Tue, 4 Feb 2014, Jason Cooper wrote:
> On Tue, Feb 04, 2014 at 07:59:58PM +0100, Thomas Gleixner wrote:
> > On Tue, 28 Jan 2014, Jason Cooper wrote:
> > > I see you pulled in mvebu/irqchip-fixes. Thanks for that. It's getting
> > > near to the end of the merge window and there's been no activity on this
> > > pull request.
> > >
> > > Please let us know if there's anything we can do to assist.
> >
> > Nah. I simply forgot about it. About to send a pull request to Linus.
>
> hmmm. I see the pull request contains the patches from
> mvebu/irqchip-fixes (armada), but not the patches from mvebu/irqchip
> (dove):
>
> 40b367d95fb3 irqchip: irq-dove: Add PMU interrupt controller.
>
> which is what this thread was originally a pull request for.
>
>
> Are you planning to send a second pull request to Linus?
Duh. I'll pick that up tomorrow
^ permalink raw reply
* [PATCH 4/6] regulator: add bcm59056 regulator driver
From: Matt Porter @ 2014-02-04 21:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140204172836.GH22609@sirena.org.uk>
On Tue, Feb 04, 2014 at 05:28:36PM +0000, Mark Brown wrote:
> On Tue, Feb 04, 2014 at 07:19:10AM -0500, Matt Porter wrote:
>
> > +static unsigned int bcm59056_get_mode(struct regulator_dev *dev)
> > +{
> > + return REGULATOR_MODE_NORMAL;
> > +}
> > +
> > +static int bcm59056_set_mode(struct regulator_dev *dev, unsigned int mode)
> > +{
> > + if (mode == REGULATOR_MODE_NORMAL)
> > + return 0;
> > + else
> > + return -EINVAL;
> > +}
>
> These do nothing, don't implement them.
Will remove. Maybe some day.
> > + if (bcm59056->dev->of_node)
> > + pmu_data = bcm59056_parse_dt_reg_data(pdev,
> > + &bcm59056_reg_matches);
>
> It'd seem a bit neater to put the OF check into the parse function but
> meh.
On second look, I'd agree. Easy enough to clean up.
> > + if (!pmu_data) {
> > + dev_err(&pdev->dev, "Platform data not found\n");
> > + return -EINVAL;
> > + }
>
> Like I said when reviewing the binding this should not cause the driver
> to fail to load.
Will fix.
> > + /*
> > + * Regulator API handles empty constraints but not NULL
> > + * constraints
> > + */
> > + if (!reg_data)
> > + continue;
>
> It should do... if not then make it so since that'd mean most drivers
> are buggy.
Ahh, I see there is a check for NULL in the core. Will drop.
-Matt
^ permalink raw reply
* [Patch v5 1/2] dmaengine: add Qualcomm BAM dma driver
From: Joe Perches @ 2014-02-04 21:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391546556-27702-2-git-send-email-agross@codeaurora.org>
On Tue, 2014-02-04 at 14:42 -0600, Andy Gross wrote:
> Add the DMA engine driver for the QCOM Bus Access Manager (BAM) DMA controller
> found in the MSM 8x74 platforms.
trivia: fixable later.
> diff --git a/drivers/dma/qcom_bam_dma.c b/drivers/dma/qcom_bam_dma.c
[]
> + /* allocate enough room to accomodate the number of entries */
> + async_desc = kzalloc(sizeof(*async_desc) +
> + (sg_len * sizeof(struct bam_desc_hw)), GFP_NOWAIT);
> +
> + if (!async_desc) {
> + dev_err(bdev->dev, "failed to allocate async descriptor\n");
Unnecessary OOM message as generic alloc has an
OOM message with a dump_stack();
> +static int bam_dma_probe(struct platform_device *pdev)
> +{
[]
> + ret = clk_prepare_enable(bdev->bamclk);
> + if (ret) {
> + dev_err(bdev->dev, "failed to prepare/enable clock");
Missing terminating \n newline
^ permalink raw reply
* [PATCH 2/6] regulator: add bcm59056 pmu DT binding
From: Matt Porter @ 2014-02-04 21:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140204172309.GG22609@sirena.org.uk>
On Tue, Feb 04, 2014 at 05:23:09PM +0000, Mark Brown wrote:
> On Tue, Feb 04, 2014 at 07:19:08AM -0500, Matt Porter wrote:
> > Add a DT binding for the BCM59056 PMU. The binding inherits from
> > the generic regulator bindings.
>
> Is this really only a regulator - does the chip have no other functions?
It's your average multi-function device with other functions as you are
suspecting. Buried in the the MFD driver comments is me admitting that
I need to split this into two bindings. The base device, "bcm59056" and
then "bcm59056-reg". So point noted, I'll updated with the appropriate
binding for each.
> > +- regulators: This is the list of child nodes that specify the regulator
> > + initialization data for defined regulators. Generic regulator bindings
> > + are described in regulator/regulator.txt.
>
> The regulators property should always be optional, the driver should be
> able to start up and read back the hardware state without any further
> configuration.
Ahh, ok. I will make it so.
Thanks,
Matt
^ permalink raw reply
* [GIT PULL] irqchip: dove: drivers for v3.14
From: Jason Cooper @ 2014-02-04 21:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.02.1402041959110.24986@ionos.tec.linutronix.de>
On Tue, Feb 04, 2014 at 07:59:58PM +0100, Thomas Gleixner wrote:
> On Tue, 28 Jan 2014, Jason Cooper wrote:
> > I see you pulled in mvebu/irqchip-fixes. Thanks for that. It's getting
> > near to the end of the merge window and there's been no activity on this
> > pull request.
> >
> > Please let us know if there's anything we can do to assist.
>
> Nah. I simply forgot about it. About to send a pull request to Linus.
hmmm. I see the pull request contains the patches from
mvebu/irqchip-fixes (armada), but not the patches from mvebu/irqchip
(dove):
40b367d95fb3 irqchip: irq-dove: Add PMU interrupt controller.
which is what this thread was originally a pull request for.
Are you planning to send a second pull request to Linus?
thx,
Jason.
^ permalink raw reply
* [PATCH v5 4/6] spmi: pmic_arb: add support for interrupt handling
From: Josh Cartwright @ 2014-02-04 20:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.02.1402042107311.24986@ionos.tec.linutronix.de>
On Tue, Feb 04, 2014 at 09:10:45PM +0100, Thomas Gleixner wrote:
> On Mon, 3 Feb 2014, Josh Cartwright wrote:
> > +static void qpnpint_irq_ack(struct irq_data *d)
> > +{
> > + struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
> > + u8 irq = d->hwirq >> 8;
> > + u8 apid = d->hwirq;
> > + unsigned long flags;
> > + u8 data;
> > +
> > + spin_lock_irqsave(&pa->lock, flags);
>
> This wants to be a raw_spinlock - think about RT!
Indeed. I'll change this in the next revision.
> Looks sane otherwise.
Great, thanks for taking a look!
Josh
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply
* [PATCH 2/4] pinctrl: st: add stid127 support
From: Linus Walleij @ 2014-02-04 20:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391093744-19905-3-git-send-email-patrice.chotard@st.com>
On Thu, Jan 30, 2014 at 3:55 PM, Patrice CHOTARD <patrice.chotard@st.com> wrote:
> From: Alexandre TORGUE <alexandre.torgue@st.com>
>
> Add STid127 PIOs (psouth, pwest, peast) in pinctrl.
>
> Signed-off-by: alexandre torgue <alexandre.torgue@st.com>
Patch applied with Srinivas ACK.
Yours,
Linus Walleij
^ permalink raw reply
* [GIT PULL] tree-wide: clean up no longer required #include <linux/init.h>
From: Paul Gortmaker @ 2014-02-04 20:51 UTC (permalink / raw)
To: linux-arm-kernel
We've had this in linux-next for 2+ weeks (thanks Stephen!) as a
linux-stable like queue of patches, and as can be seen here:
https://git.kernel.org/pub/scm/linux/kernel/git/paulg/init.git
most of the changes in the last week have been trivial adding acks
or dropping patches that maintainers decided to take themselves.
With -rc1 now containing what was in linux-next, the queue applies
to that baseline w/o issue, and I've redone comprehensive multi
arch build testing on the -rc1 baseline as a final sanity check.
Original RFC discussion and patch posting is here, if needed:
https://lkml.org/lkml/2014/1/21/434
Suggested merge text follows:
----------------------------8<-----------------------------
Summary - We removed cpuinit and devinit, which left ~2000 instances
of include <linux/init.h> that were no longer needed. To fully enable
this removal/cleanup, we relocate module_init() from init.h into
module.h. Multi arch/multi config build testing on linux-next has
been used to find and fix any implicit header dependencies prior to
deploying the actual init.h --> module.h move, to preserve bisection.
Additional details:
module_init/module_exit and friends moved to module.h
-----------------------------------------------------
Aside from enabling this init.h cleanup to extend into modular files,
it actually does make sense. For all modules will use some form of
our initfunc processing/categorization, but not all initfunc users
will be necessarily using modular functionality. So we move these
module related macros to module.h and ensure module.h sources init.h
module_init in non modular code:
--------------------------------
This series uncovered that we are enabling people to use module_init
in non-modular code. While that works fine, there are at least three
reasons why it probably should not be encouraged:
1) it makes a casual reader of the code assume the code is modular
even though it is obj-y (builtin) or controlled by a bool Kconfig.
2) it makes it too easy to add dead code in a function that is handed
to module_exit() -- [more on that below]
3) it breaks our ability to use priority sorted initcalls properly
[more on that below.]
4) on some files, the use of module.h vs. init.h can cost a ~10%
increase in the number of lines output from CPP.
After this change, a new coder who tries to make use of module_init in
non modular code would find themselves also needing to include the
module.h header. At which point the odds are greater that they would
ask themselves "Am I doing this right? I shouldn't need this."
Note that existing non-modular code that already includes module.h and
uses module_init doesn't get fixed here, since they already build w/o
errors triggered by this change; we'll have to hunt them down later.
module_init and initcall ordering:
----------------------------------
We have a group of about ten priority sorted initcalls, that are
called in init/main.c after most of the hard coded/direct calls
have been processed. These serve the purpose of avoiding everyone
poking at init/main.c to hook in their init sequence. The bins are:
pure_initcall 0
core_initcall 1
postcore_initcall 2
arch_initcall 3
subsys_initcall 4
fs_initcall 5
device_initcall 6
late_initcall 7
These are meant to eventually replace users of the non specific
priority "__initcall" which currently maps onto device_initcall.
This is of interest, because in non-modular code, cpp does this:
module_init --> __initcall --> device_initcall
So all module_init() land in the device_initcall bucket, rather late
in the sequence. That makes sense, since if it was a module, the init
could be real late (days, weeks after boot). But now imagine you add
support for some non-modular bus/arch/infrastructure (say for e.g. PCI)
and you use module_init for it. That means anybody else who wants
to use your subsystem can't do so if they use an initcall of 0 --> 5
priority. For a real world example of this, see patch #1 in this series:
https://lkml.org/lkml/2014/1/14/809
We don't want to force code that is clearly arch or subsys or fs
specific to have to use the device_initcall just because something
else has been mistakenly put (or left) in that bucket. So a couple of
changes do actually change the initcall level where it is inevitably
appropriate to do so. Those are called out explicitly in their
respective commit logs.
module_exit and dead code
-------------------------
Built in code will never have an opportunity to call functions that
are registered with module_exit(), so any cases of that uncovered in
this series delete that dead code. Note that any built-in code that
was already including module.h and using module_exit won't have shown
up as breakage on the build coverage of this series, so we'll have to
find those independently later. It looks like there may be quite a
few that are invisibly created via module_platform_driver -- a macro
that creates module_init and module_exit automatically. We may want
to consider relocating module_platform_driver into module.h later...
cpuinit
-------
To finalize the removal of cpuinit, which was done several releases
ago, we remove the remaining stub functions from init.h in this
series. We've seen one or two "users" try to creep back in, so this
will close the door on that chapter and prevent creep.
----------------------------8<-----------------------------
Thanks,
Paul.
---
Cc: linux-alpha at vger.kernel.org
Cc: linux-arch at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-ia64 at vger.kernel.org
Cc: linux-m68k at lists.linux-m68k.org
Cc: linux-mips at linux-mips.org
Cc: linuxppc-dev at lists.ozlabs.org
Cc: linux-s390 at vger.kernel.org
Cc: sparclinux at vger.kernel.org
Cc: x86 at kernel.org
Cc: netdev at vger.kernel.org
Cc: kvm at vger.kernel.org
Cc: sfr at canb.auug.org.au
Cc: rusty at rustcorp.com.au
Cc: gregkh at linuxfoundation.org
Cc: akpm at linux-foundation.org
Cc: torvalds@linux-foundation.org
The following changes since commit 38dbfb59d1175ef458d006556061adeaa8751b72:
Linus 3.14-rc1 (2014-02-02 16:42:13 -0800)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/paulg/linux.git tags/init-cleanup
for you to fetch changes up to a830e2e2777c893e5bfdaa370d6375023e8cd2a5:
include: remove needless instances of <linux/init.h> (2014-02-03 16:39:14 -0500)
----------------------------------------------------------------
Cleanup of <linux/init.h> for 3.14-rc1
----------------------------------------------------------------
Paul Gortmaker (77):
init: delete the __cpuinit related stubs
kernel: audit/fix non-modular users of module_init in core code
mm: replace module_init usages with subsys_initcall in nommu.c
fs/notify: don't use module_init for non-modular inotify_user code
netfilter: don't use module_init/exit in core IPV4 code
x86: don't use module_init in non-modular intel_mid_vrtc.c
x86: don't use module_init for non-modular core bootflag code
x86: replace __init_or_module with __init in non-modular vsmp_64.c
x86: don't use module_init in non-modular devicetree.c code
drivers/tty/hvc: don't use module_init in non-modular hyp. console code
staging: don't use module_init in non-modular ion_dummy_driver.c
powerpc: use device_initcall for registering rtc devices
powerpc: use subsys_initcall for Freescale Local Bus
powerpc: don't use module_init for non-modular core hugetlb code
powerpc: don't use module_init in non-modular 83xx suspend code
arm: include module.h in drivers/bus/omap_l3_smx.c
arm: fix implicit module.h use in mach-at91 gpio.h
arm: fix implicit #include <linux/init.h> in entry asm.
arm: mach-s3c64xx mach-crag6410-module.c is not modular
arm: use subsys_initcall in non-modular pl320 IPC code
arm: don't use module_init in non-modular mach-vexpress/spc.c code
alpha: don't use module_init for non-modular core code
m68k: don't use module_init in non-modular mvme16x/rtc.c code
ia64: don't use module_init for non-modular core kernel/mca.c code
ia64: don't use module_init in non-modular sim/simscsi.c code
mips: make loongsoon serial driver explicitly modular
mips: don't use module_init in non-modular sead3-mtd.c code
cris: don't use module_init for non-modular core intmem.c code
parisc: don't use module_init for non-modular core pdc_cons code
parisc64: don't use module_init for non-modular core perf code
mn10300: don't use module_init in non-modular flash.c code
sh: don't use module_init in non-modular psw.c code
sh: mach-highlander/psw.c is tristate and should use module.h
xtensa: don't use module_init for non-modular core network.c code
drivers/clk: don't use module_init in clk-nomadik.c which is non-modular
cpuidle: don't use modular platform register in non-modular ARM drivers
drivers/platform: don't use modular register in non-modular pdev_bus.c
module: relocate module_init from init.h to module.h
logo: emit "#include <linux/init.h> in autogenerated C file
arm: delete non-required instances of include <linux/init.h>
mips: restore init.h usage to arch/mips/ar7/time.c
s390: delete non-required instances of include <linux/init.h>
alpha: delete non-required instances of <linux/init.h>
powerpc: delete another unrequired instance of <linux/init.h>
arm64: delete non-required instances of <linux/init.h>
watchdog: delete non-required instances of include <linux/init.h>
video: delete non-required instances of include <linux/init.h>
rtc: delete non-required instances of include <linux/init.h>
scsi: delete non-required instances of include <linux/init.h>
spi: delete non-required instances of include <linux/init.h>
acpi: delete non-required instances of include <linux/init.h>
drivers/power: delete non-required instances of include <linux/init.h>
drivers/media: delete non-required instances of include <linux/init.h>
drivers/ata: delete non-required instances of include <linux/init.h>
drivers/hwmon: delete non-required instances of include <linux/init.h>
drivers/pinctrl: delete non-required instances of include <linux/init.h>
drivers/isdn: delete non-required instances of include <linux/init.h>
drivers/leds: delete non-required instances of include <linux/init.h>
drivers/pcmcia: delete non-required instances of include <linux/init.h>
drivers/char: delete non-required instances of include <linux/init.h>
drivers/infiniband: delete non-required instances of include <linux/init.h>
drivers/mfd: delete non-required instances of include <linux/init.h>
drivers/gpio: delete non-required instances of include <linux/init.h>
drivers/bluetooth: delete non-required instances of include <linux/init.h>
drivers/mmc: delete non-required instances of include <linux/init.h>
drivers/crypto: delete non-required instances of include <linux/init.h>
drivers/platform: delete non-required instances of include <linux/init.h>
drivers/misc: delete non-required instances of include <linux/init.h>
drivers/edac: delete non-required instances of include <linux/init.h>
drivers/macintosh: delete non-required instances of include <linux/init.h>
drivers/base: delete non-required instances of include <linux/init.h>
drivers/cpufreq: delete non-required instances of <linux/init.h>
drivers/pci: delete non-required instances of <linux/init.h>
drivers/dma: delete non-required instances of <linux/init.h>
drivers/gpu: delete non-required instances of <linux/init.h>
drivers: delete remaining non-required instances of <linux/init.h>
include: remove needless instances of <linux/init.h>
arch/alpha/kernel/err_ev6.c | 1 -
arch/alpha/kernel/irq.c | 1 -
arch/alpha/kernel/srmcons.c | 3 +-
arch/alpha/kernel/traps.c | 1 -
arch/alpha/oprofile/op_model_ev4.c | 1 -
arch/alpha/oprofile/op_model_ev5.c | 1 -
arch/alpha/oprofile/op_model_ev6.c | 1 -
arch/alpha/oprofile/op_model_ev67.c | 1 -
arch/arm/common/dmabounce.c | 1 -
arch/arm/firmware/trusted_foundations.c | 1 -
arch/arm/include/asm/arch_timer.h | 1 -
arch/arm/kernel/entry-armv.S | 2 +
arch/arm/kernel/entry-header.S | 1 -
arch/arm/kernel/hyp-stub.S | 1 -
arch/arm/kernel/suspend.c | 1 -
arch/arm/kernel/unwind.c | 1 -
arch/arm/mach-at91/include/mach/gpio.h | 1 +
arch/arm/mach-cns3xxx/pm.c | 1 -
arch/arm/mach-exynos/headsmp.S | 1 -
arch/arm/mach-footbridge/personal.c | 1 -
arch/arm/mach-imx/headsmp.S | 1 -
arch/arm/mach-imx/iomux-v3.c | 1 -
arch/arm/mach-iop33x/uart.c | 1 -
arch/arm/mach-msm/headsmp.S | 1 -
arch/arm/mach-msm/proc_comm.h | 1 -
arch/arm/mach-mvebu/headsmp.S | 1 -
arch/arm/mach-netx/fb.c | 1 -
arch/arm/mach-netx/pfifo.c | 1 -
arch/arm/mach-netx/xc.c | 1 -
arch/arm/mach-nspire/clcd.c | 1 -
arch/arm/mach-omap1/fpga.c | 1 -
arch/arm/mach-omap1/include/mach/serial.h | 1 -
arch/arm/mach-omap2/omap-headsmp.S | 1 -
arch/arm/mach-omap2/omap3-restart.c | 1 -
arch/arm/mach-omap2/vc3xxx_data.c | 1 -
arch/arm/mach-omap2/vc44xx_data.c | 1 -
arch/arm/mach-omap2/vp3xxx_data.c | 1 -
arch/arm/mach-omap2/vp44xx_data.c | 1 -
arch/arm/mach-prima2/headsmp.S | 1 -
arch/arm/mach-pxa/clock-pxa2xx.c | 1 -
arch/arm/mach-pxa/clock-pxa3xx.c | 1 -
arch/arm/mach-pxa/corgi_pm.c | 1 -
arch/arm/mach-pxa/mfp-pxa3xx.c | 1 -
arch/arm/mach-pxa/spitz_pm.c | 1 -
arch/arm/mach-s3c24xx/clock-s3c244x.c | 1 -
arch/arm/mach-s3c24xx/iotiming-s3c2410.c | 1 -
arch/arm/mach-s3c24xx/iotiming-s3c2412.c | 1 -
arch/arm/mach-s3c24xx/irq-pm.c | 1 -
arch/arm/mach-s3c24xx/pm.c | 1 -
arch/arm/mach-s3c64xx/mach-crag6410-module.c | 2 +-
arch/arm/mach-s5p64x0/clock.c | 1 -
arch/arm/mach-sa1100/ssp.c | 1 -
arch/arm/mach-shmobile/headsmp-scu.S | 1 -
arch/arm/mach-shmobile/headsmp.S | 1 -
arch/arm/mach-shmobile/platsmp.c | 1 -
arch/arm/mach-shmobile/sleep-sh7372.S | 1 -
arch/arm/mach-socfpga/headsmp.S | 1 -
arch/arm/mach-sti/headsmp.S | 1 -
arch/arm/mach-sunxi/headsmp.S | 1 -
arch/arm/mach-tegra/flowctrl.c | 1 -
arch/arm/mach-tegra/headsmp.S | 1 -
arch/arm/mach-tegra/reset-handler.S | 1 -
arch/arm/mach-u300/dummyspichip.c | 1 -
arch/arm/mach-ux500/board-mop500-audio.c | 1 -
arch/arm/mach-ux500/headsmp.S | 1 -
arch/arm/mach-versatile/versatile_ab.c | 1 -
arch/arm/mach-vexpress/spc.c | 2 +-
arch/arm/mach-zynq/headsmp.S | 1 -
arch/arm/mm/hugetlbpage.c | 1 -
arch/arm/plat-iop/i2c.c | 1 -
arch/arm/plat-samsung/pm-check.c | 1 -
arch/arm/plat-samsung/pm-gpio.c | 1 -
arch/arm/plat-samsung/s5p-irq-pm.c | 1 -
arch/arm/plat-versatile/headsmp.S | 1 -
arch/arm/plat-versatile/platsmp.c | 1 -
arch/arm/vfp/entry.S | 2 +
arch/arm64/include/asm/arch_timer.h | 1 -
arch/arm64/kernel/cputable.c | 2 -
arch/arm64/kernel/entry.S | 1 -
arch/arm64/kernel/hyp-stub.S | 1 -
arch/arm64/kernel/process.c | 1 -
arch/arm64/kernel/ptrace.c | 1 -
arch/arm64/kernel/smp_spin_table.c | 1 -
arch/arm64/kernel/vdso/vdso.S | 1 -
arch/arm64/lib/delay.c | 1 -
arch/arm64/mm/cache.S | 1 -
arch/arm64/mm/proc.S | 1 -
arch/cris/arch-v32/mm/intmem.c | 3 +-
arch/ia64/hp/sim/simscsi.c | 11 +---
arch/ia64/sn/kernel/mca.c | 3 +-
arch/m68k/mvme16x/rtc.c | 2 +-
arch/mips/ar7/time.c | 1 +
arch/mips/loongson/common/serial.c | 9 ++-
arch/mips/mti-sead3/sead3-mtd.c | 3 +-
arch/mn10300/unit-asb2303/flash.c | 3 +-
arch/parisc/kernel/pdc_cons.c | 3 +-
arch/parisc/kernel/perf.c | 3 +-
arch/powerpc/kernel/time.c | 2 +-
arch/powerpc/mm/hugetlbpage.c | 2 +-
arch/powerpc/platforms/83xx/suspend.c | 3 +-
arch/powerpc/platforms/ps3/time.c | 3 +-
arch/powerpc/sysdev/fsl_lbc.c | 2 +-
arch/powerpc/sysdev/indirect_pci.c | 1 -
arch/sh/boards/mach-highlander/psw.c | 2 +-
arch/sh/boards/mach-landisk/psw.c | 2 +-
arch/x86/kernel/bootflag.c | 2 +-
arch/x86/kernel/devicetree.c | 2 +-
arch/x86/kernel/vsmp_64.c | 2 +-
arch/x86/platform/intel-mid/intel_mid_vrtc.c | 3 +-
arch/xtensa/platforms/iss/network.c | 4 +-
drivers/acpi/apei/apei-base.c | 1 -
drivers/acpi/button.c | 1 -
[ ... snip ~1000 lines of trivial driver diffstat ... ]
drivers/watchdog/wdt_pci.c | 1 -
drivers/xen/xen-stub.c | 1 -
fs/notify/inotify/inotify_user.c | 4 +-
include/drm/drmP.h | 1 -
include/linux/fb.h | 1 -
include/linux/ide.h | 1 -
include/linux/init.h | 77 ----------------------
include/linux/kdb.h | 1 -
include/linux/linux_logo.h | 3 -
include/linux/lsm_audit.h | 1 -
include/linux/module.h | 72 ++++++++++++++++++++
include/linux/moduleparam.h | 1 -
include/linux/netfilter.h | 1 -
include/linux/nls.h | 2 +-
include/linux/percpu_ida.h | 1 -
include/linux/profile.h | 1 -
include/linux/pstore_ram.h | 1 -
include/linux/usb/gadget.h | 1 -
include/xen/xenbus.h | 1 -
kernel/hung_task.c | 3 +-
kernel/kexec.c | 4 +-
kernel/profile.c | 2 +-
kernel/sched/stats.c | 2 +-
kernel/user.c | 3 +-
kernel/user_namespace.c | 2 +-
mm/nommu.c | 4 +-
net/ipv4/netfilter.c | 9 +--
scripts/pnmtologo.c | 1 +
scripts/tags.sh | 2 +-
1115 files changed, 148 insertions(+), 1273 deletions(-)
^ permalink raw reply
* [PATCH 2/2] ARM: dts: sirf: add pin group for USP0 with only RX or TX frame sync for atlas6
From: Linus Walleij @ 2014-02-04 20:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391061293-2195-1-git-send-email-21cnbao@gmail.com>
On Thu, Jan 30, 2014 at 6:54 AM, Barry Song <21cnbao@gmail.com> wrote:
> From: Rongjun Ying <rongjun.ying@csr.com>
>
> add pin groups for USP0 only holding one of TX and RX frame sync. this patch
> matches with the change in drivers/pinctrl/sirf.
>
> commit 73f68c01f46 did this for prima2, but missed prima2. this patch fixes
> the problem.
>
> Signed-off-by: Rongjun Ying <rongjun.ying@csr.com>
> Signed-off-by: Barry Song <Baohua.Song@csr.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Please take this patch through the ARM SoC tree.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH 1/2] pinctrl: sirf: add pin group for USP0 with only RX or TX frame sync for atlas6
From: Linus Walleij @ 2014-02-04 20:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391061264-2162-1-git-send-email-21cnbao@gmail.com>
On Thu, Jan 30, 2014 at 6:54 AM, Barry Song <21cnbao@gmail.com> wrote:
> From: Rongjun Ying <rongjun.ying@csr.com>
>
> USP0 has multiple functions, and has RX and TX frame sync signals, for some scenarios
> like audio PCM, we don't need both of them. so here we add two possibilities for USP0
> only holding one of TX and RX frame sync.
>
> commit 8385af02bad only added this group for prima2, and missed atlas6. her this patch
> fixes it.
>
> Signed-off-by: Rongjun Ying <rongjun.ying@csr.com>
> Signed-off-by: Barry Song <Baohua.Song@csr.com>
Patch applied. Altered the commit message a bit.
Yours,
Linus Walleij
^ permalink raw reply
* Weird sched_clock behaviour during boot with -rc1
From: John Stultz @ 2014-02-04 20:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140204183641.GA25127@mudshark.cambridge.arm.com>
On 02/04/2014 10:36 AM, Will Deacon wrote:
> Hi guys,
>
> Booting -rc1 on my TC2 gives the following strange entries in the dmesg:
>
>
> Uncompressing Linux... done, booting the kernel.
> [ 0.000000] Booting Linux on physical CPU 0x0
>
> [...]
>
> [ 0.000000] HighMem zone: 329728 pages, LIFO batch:31
> [ 7.789662] sched_clock: 32 bits at 24MHz, resolution 41ns, wraps every 178956969942ns
> [ 0.000129] PERCPU: Embedded 9 pages/cpu @ee7bd000 s12800 r8192 d15872 u36864
>
> [...]
>
> [ 0.868297] NR_IRQS:16 nr_irqs:16 16
> [ 0.886350] Architected cp15 timer(s) running at 24.00MHz (phys).
> [ 2915.164998] sched_clock: 56 bits at 24MHz, resolution 41ns, wraps every 2863311519744ns
> [ 0.000002] Switching to timer-based delay loop
> [ 0.014249] Console: colour dummy device 80x30
>
>
> so it looks like something whacky goes on during sched_clock registration.
> Sure enough, we're doing a pr_info in-between updating cs.* and calling
> update_sched_clock(), so moving the print sorts things out (diff below).
Yea... we have to be particularly careful with sched_clock to avoid
locks since we don't want to deadlock, but in this case
sched_clock_register is a little too relaxed here.
Stephen: Would it make sense to set cd.suspended = true at the top of
the registration? That should block any sched_clock calls from getting
half-updated data, but still allow the sched_clock_update function to work.
> What I can't figure out is why this has suddenly started happening with
> 3.14. Any ideas?
No clue. I'm guessing something like timing changes in the printk paths
that call sched_clock?
I suspect your patch to move the print down will also be a good idea
along with the suspending sched_clock while we register new ones.
thanks
-john
^ permalink raw reply
* [Patch v5 2/2] dmaengine: qcom_bam_dma: Add device tree binding
From: Andy Gross @ 2014-02-04 20:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391546556-27702-1-git-send-email-agross@codeaurora.org>
Add device tree binding support for the QCOM BAM DMA driver.
Signed-off-by: Andy Gross <agross@codeaurora.org>
---
.../devicetree/bindings/dma/qcom_bam_dma.txt | 48 ++++++++++++++++++++
1 file changed, 48 insertions(+)
create mode 100644 Documentation/devicetree/bindings/dma/qcom_bam_dma.txt
diff --git a/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt b/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt
new file mode 100644
index 0000000..86344f1
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt
@@ -0,0 +1,48 @@
+QCOM BAM DMA controller
+
+Required properties:
+- compatible: Must be "qcom,bam-v1.4.0" for MSM8974 V1
+ Must be "qcom,bam-v1.4.1" for MSM8974 V2
+- reg: Address range for DMA registers
+- interrupts: single interrupt for this controller
+- #dma-cells: must be <1>
+- clocks: required clock
+- clock-names: name of clock
+- qcom,ee : indicates the active Execution Environment identifier (0-7)
+
+Example:
+
+ uart-bam: dma at f9984000 = {
+ compatible = "qcom,bam-v1.4.1";
+ reg = <0xf9984000 0x15000>;
+ interrupts = <0 94 0>;
+ clocks = <&gcc GCC_BAM_DMA_AHB_CLK>;
+ clock-names = "bam_clk";
+ #dma-cells = <1>;
+ qcom,ee = <0>;
+ };
+
+Client:
+Required properties:
+- dmas: List of dma channel requests
+- dma-names: Names of aforementioned requested channels
+
+Clients must use the format described in the dma.txt file, using a two cell
+specifier for each channel.
+
+The three cells in order are:
+ 1. A phandle pointing to the DMA controller
+ 2. The channel number
+
+Example:
+ serial at f991e000 {
+ compatible = "qcom,msm-uart";
+ reg = <0xf991e000 0x1000>
+ <0xf9944000 0x19000>;
+ interrupts = <0 108 0>;
+ clocks = <&gcc GCC_BLSP1_UART2_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>;
+ clock-names = "core", "iface";
+
+ dmas = <&uart-bam 0>, <&uart-bam 1>;
+ dma-names = "rx", "tx";
+ };
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply related
* [Patch v5 1/2] dmaengine: add Qualcomm BAM dma driver
From: Andy Gross @ 2014-02-04 20:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391546556-27702-1-git-send-email-agross@codeaurora.org>
Add the DMA engine driver for the QCOM Bus Access Manager (BAM) DMA controller
found in the MSM 8x74 platforms.
Each BAM DMA device is associated with a specific on-chip peripheral. Each
channel provides a uni-directional data transfer engine that is capable of
transferring data between the peripheral and system memory (System mode), or
between two peripherals (BAM2BAM).
The initial release of this driver only supports slave transfers between
peripherals and system memory.
Signed-off-by: Andy Gross <agross@codeaurora.org>
---
drivers/dma/Kconfig | 9 +
drivers/dma/Makefile | 1 +
drivers/dma/qcom_bam_dma.c | 1066 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 1076 insertions(+)
create mode 100644 drivers/dma/qcom_bam_dma.c
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index c10eb89..1b2f6cf 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -386,4 +386,13 @@ config DMATEST
config DMA_ENGINE_RAID
bool
+config QCOM_BAM_DMA
+ tristate "QCOM BAM DMA support"
+ depends on ARCH_MSM_DT || (COMPILE_TEST && OF && ARM)
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
+ ---help---
+ Enable support for the QCOM BAM DMA controller. This controller
+ provides DMA capabilities for a variety of on-chip devices.
+
endif
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 0ce2da9..7ef950a 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -42,3 +42,4 @@ obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o
obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o
obj-$(CONFIG_TI_CPPI41) += cppi41.o
obj-$(CONFIG_K3_DMA) += k3dma.o
+obj-$(CONFIG_QCOM_BAM_DMA) += qcom_bam_dma.o
diff --git a/drivers/dma/qcom_bam_dma.c b/drivers/dma/qcom_bam_dma.c
new file mode 100644
index 0000000..214250c
--- /dev/null
+++ b/drivers/dma/qcom_bam_dma.c
@@ -0,0 +1,1066 @@
+/*
+ * QCOM BAM DMA engine driver
+ *
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ *
+ * QCOM BAM DMA blocks are distributed amongst a number of the on-chip
+ * peripherals on the MSM 8x74. The configuration of the channels are dependent
+ * on the way they are hard wired to that specific peripheral. The peripheral
+ * device tree entries specify the configuration of each channel.
+ *
+ * The DMA controller requires the use of external memory for storage of the
+ * hardware descriptors for each channel. The descriptor FIFO is accessed as a
+ * circular buffer and operations are managed according to the offset within the
+ * FIFO. After pipe/channel reset, all of the pipe registers and internal state
+ * are back to defaults.
+ *
+ * During DMA operations, we write descriptors to the FIFO, being careful to
+ * handle wrapping and then write the last FIFO offset to that channel's
+ * P_EVNT_REG register to kick off the transaction. The P_SW_OFSTS register
+ * indicates the current FIFO offset that is being processed, so there is some
+ * indication of where the hardware is currently working.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_dma.h>
+#include <linux/clk.h>
+#include <linux/dmaengine.h>
+
+#include "dmaengine.h"
+#include "virt-dma.h"
+
+struct bam_desc_hw {
+ u32 addr; /* Buffer physical address */
+ u16 size; /* Buffer size in bytes */
+ u16 flags;
+};
+
+#define DESC_FLAG_INT BIT(15)
+#define DESC_FLAG_EOT BIT(14)
+#define DESC_FLAG_EOB BIT(13)
+
+struct bam_async_desc {
+ struct virt_dma_desc vd;
+
+ u32 num_desc;
+ u32 xfer_len;
+ struct bam_desc_hw *curr_desc;
+
+ enum dma_transfer_direction dir;
+ size_t length;
+ struct bam_desc_hw desc[0];
+};
+
+#define BAM_CTRL 0x0000
+#define BAM_REVISION 0x0004
+#define BAM_SW_REVISION 0x0080
+#define BAM_NUM_PIPES 0x003C
+#define BAM_TIMER 0x0040
+#define BAM_TIMER_CTRL 0x0044
+#define BAM_DESC_CNT_TRSHLD 0x0008
+#define BAM_IRQ_SRCS 0x000C
+#define BAM_IRQ_SRCS_MSK 0x0010
+#define BAM_IRQ_SRCS_UNMASKED 0x0030
+#define BAM_IRQ_STTS 0x0014
+#define BAM_IRQ_CLR 0x0018
+#define BAM_IRQ_EN 0x001C
+#define BAM_CNFG_BITS 0x007C
+#define BAM_IRQ_SRCS_EE(pipe) (0x0800 + ((pipe) * 0x80))
+#define BAM_IRQ_SRCS_MSK_EE(pipe) (0x0804 + ((pipe) * 0x80))
+#define BAM_P_CTRL(pipe) (0x1000 + ((pipe) * 0x1000))
+#define BAM_P_RST(pipe) (0x1004 + ((pipe) * 0x1000))
+#define BAM_P_HALT(pipe) (0x1008 + ((pipe) * 0x1000))
+#define BAM_P_IRQ_STTS(pipe) (0x1010 + ((pipe) * 0x1000))
+#define BAM_P_IRQ_CLR(pipe) (0x1014 + ((pipe) * 0x1000))
+#define BAM_P_IRQ_EN(pipe) (0x1018 + ((pipe) * 0x1000))
+#define BAM_P_EVNT_DEST_ADDR(pipe) (0x182C + ((pipe) * 0x1000))
+#define BAM_P_EVNT_REG(pipe) (0x1818 + ((pipe) * 0x1000))
+#define BAM_P_SW_OFSTS(pipe) (0x1800 + ((pipe) * 0x1000))
+#define BAM_P_DATA_FIFO_ADDR(pipe) (0x1824 + ((pipe) * 0x1000))
+#define BAM_P_DESC_FIFO_ADDR(pipe) (0x181C + ((pipe) * 0x1000))
+#define BAM_P_EVNT_TRSHLD(pipe) (0x1828 + ((pipe) * 0x1000))
+#define BAM_P_FIFO_SIZES(pipe) (0x1820 + ((pipe) * 0x1000))
+
+/* BAM CTRL */
+#define BAM_SW_RST BIT(0)
+#define BAM_EN BIT(1)
+#define BAM_EN_ACCUM BIT(4)
+#define BAM_TESTBUS_SEL_SHIFT 5
+#define BAM_TESTBUS_SEL_MASK 0x3F
+#define BAM_DESC_CACHE_SEL_SHIFT 13
+#define BAM_DESC_CACHE_SEL_MASK 0x3
+#define BAM_CACHED_DESC_STORE BIT(15)
+#define IBC_DISABLE BIT(16)
+
+/* BAM REVISION */
+#define REVISION_SHIFT 0
+#define REVISION_MASK 0xFF
+#define NUM_EES_SHIFT 8
+#define NUM_EES_MASK 0xF
+#define CE_BUFFER_SIZE BIT(13)
+#define AXI_ACTIVE BIT(14)
+#define USE_VMIDMT BIT(15)
+#define SECURED BIT(16)
+#define BAM_HAS_NO_BYPASS BIT(17)
+#define HIGH_FREQUENCY_BAM BIT(18)
+#define INACTIV_TMRS_EXST BIT(19)
+#define NUM_INACTIV_TMRS BIT(20)
+#define DESC_CACHE_DEPTH_SHIFT 21
+#define DESC_CACHE_DEPTH_1 (0 << DESC_CACHE_DEPTH_SHIFT)
+#define DESC_CACHE_DEPTH_2 (1 << DESC_CACHE_DEPTH_SHIFT)
+#define DESC_CACHE_DEPTH_3 (2 << DESC_CACHE_DEPTH_SHIFT)
+#define DESC_CACHE_DEPTH_4 (3 << DESC_CACHE_DEPTH_SHIFT)
+#define CMD_DESC_EN BIT(23)
+#define INACTIV_TMR_BASE_SHIFT 24
+#define INACTIV_TMR_BASE_MASK 0xFF
+
+/* BAM NUM PIPES */
+#define BAM_NUM_PIPES_SHIFT 0
+#define BAM_NUM_PIPES_MASK 0xFF
+#define PERIPH_NON_PIPE_GRP_SHIFT 16
+#define PERIPH_NON_PIP_GRP_MASK 0xFF
+#define BAM_NON_PIPE_GRP_SHIFT 24
+#define BAM_NON_PIPE_GRP_MASK 0xFF
+
+/* BAM CNFG BITS */
+#define BAM_PIPE_CNFG BIT(2)
+#define BAM_FULL_PIPE BIT(11)
+#define BAM_NO_EXT_P_RST BIT(12)
+#define BAM_IBC_DISABLE BIT(13)
+#define BAM_SB_CLK_REQ BIT(14)
+#define BAM_PSM_CSW_REQ BIT(15)
+#define BAM_PSM_P_RES BIT(16)
+#define BAM_AU_P_RES BIT(17)
+#define BAM_SI_P_RES BIT(18)
+#define BAM_WB_P_RES BIT(19)
+#define BAM_WB_BLK_CSW BIT(20)
+#define BAM_WB_CSW_ACK_IDL BIT(21)
+#define BAM_WB_RETR_SVPNT BIT(22)
+#define BAM_WB_DSC_AVL_P_RST BIT(23)
+#define BAM_REG_P_EN BIT(24)
+#define BAM_PSM_P_HD_DATA BIT(25)
+#define BAM_AU_ACCUMED BIT(26)
+#define BAM_CMD_ENABLE BIT(27)
+
+#define BAM_CNFG_BITS_DEFAULT (BAM_PIPE_CNFG | \
+ BAM_NO_EXT_P_RST | \
+ BAM_IBC_DISABLE | \
+ BAM_SB_CLK_REQ | \
+ BAM_PSM_CSW_REQ | \
+ BAM_PSM_P_RES | \
+ BAM_AU_P_RES | \
+ BAM_SI_P_RES | \
+ BAM_WB_P_RES | \
+ BAM_WB_BLK_CSW | \
+ BAM_WB_CSW_ACK_IDL | \
+ BAM_WB_RETR_SVPNT | \
+ BAM_WB_DSC_AVL_P_RST | \
+ BAM_REG_P_EN | \
+ BAM_PSM_P_HD_DATA | \
+ BAM_AU_ACCUMED | \
+ BAM_CMD_ENABLE)
+
+/* PIPE CTRL */
+#define P_EN BIT(1)
+#define P_DIRECTION BIT(3)
+#define P_SYS_STRM BIT(4)
+#define P_SYS_MODE BIT(5)
+#define P_AUTO_EOB BIT(6)
+#define P_AUTO_EOB_SEL_SHIFT 7
+#define P_AUTO_EOB_SEL_512 (0 << P_AUTO_EOB_SEL_SHIFT)
+#define P_AUTO_EOB_SEL_256 (1 << P_AUTO_EOB_SEL_SHIFT)
+#define P_AUTO_EOB_SEL_128 (2 << P_AUTO_EOB_SEL_SHIFT)
+#define P_AUTO_EOB_SEL_64 (3 << P_AUTO_EOB_SEL_SHIFT)
+#define P_PREFETCH_LIMIT_SHIFT 9
+#define P_PREFETCH_LIMIT_32 (0 << P_PREFETCH_LIMIT_SHIFT)
+#define P_PREFETCH_LIMIT_16 (1 << P_PREFETCH_LIMIT_SHIFT)
+#define P_PREFETCH_LIMIT_4 (2 << P_PREFETCH_LIMIT_SHIFT)
+#define P_WRITE_NWD BIT(11)
+#define P_LOCK_GROUP_SHIFT 16
+#define P_LOCK_GROUP_MASK 0x1F
+
+/* BAM_DESC_CNT_TRSHLD */
+#define CNT_TRSHLD 0xffff
+#define DEFAULT_CNT_THRSHLD 0x4
+
+/* BAM_IRQ_SRCS */
+#define BAM_IRQ BIT(31)
+#define P_IRQ 0x7fffffff
+
+/* BAM_IRQ_SRCS_MSK */
+#define BAM_IRQ_MSK BAM_IRQ
+#define P_IRQ_MSK P_IRQ
+
+/* BAM_IRQ_STTS */
+#define BAM_TIMER_IRQ BIT(4)
+#define BAM_EMPTY_IRQ BIT(3)
+#define BAM_ERROR_IRQ BIT(2)
+#define BAM_HRESP_ERR_IRQ BIT(1)
+
+/* BAM_IRQ_CLR */
+#define BAM_TIMER_CLR BIT(4)
+#define BAM_EMPTY_CLR BIT(3)
+#define BAM_ERROR_CLR BIT(2)
+#define BAM_HRESP_ERR_CLR BIT(1)
+
+/* BAM_IRQ_EN */
+#define BAM_TIMER_EN BIT(4)
+#define BAM_EMPTY_EN BIT(3)
+#define BAM_ERROR_EN BIT(2)
+#define BAM_HRESP_ERR_EN BIT(1)
+
+/* BAM_P_IRQ_EN */
+#define P_PRCSD_DESC_EN BIT(0)
+#define P_TIMER_EN BIT(1)
+#define P_WAKE_EN BIT(2)
+#define P_OUT_OF_DESC_EN BIT(3)
+#define P_ERR_EN BIT(4)
+#define P_TRNSFR_END_EN BIT(5)
+#define P_DEFAULT_IRQS_EN (P_PRCSD_DESC_EN | P_ERR_EN | P_TRNSFR_END_EN)
+
+/* BAM_P_SW_OFSTS */
+#define P_SW_OFSTS_MASK 0xffff
+
+#define BAM_DESC_FIFO_SIZE SZ_32K
+#define MAX_DESCRIPTORS (BAM_DESC_FIFO_SIZE / sizeof(struct bam_desc_hw) - 1)
+#define BAM_MAX_DATA_SIZE (SZ_32K - 8)
+
+struct bam_chan {
+ struct virt_dma_chan vc;
+
+ struct bam_device *bdev;
+
+ /* configuration from device tree */
+ u32 id;
+ u32 ee;
+
+ struct bam_async_desc *curr_txd; /* current running dma */
+
+ /* runtime configuration */
+ struct dma_slave_config slave;
+
+ /* fifo storage */
+ struct bam_desc_hw *fifo_virt;
+ dma_addr_t fifo_phys;
+
+ /* fifo markers */
+ unsigned short head; /* start of active descriptor entries */
+ unsigned short tail; /* end of active descriptor entries */
+
+ unsigned int initialized; /* is the channel hw initialized? */
+ unsigned int paused; /* is the channel paused? */
+
+ struct list_head node;
+};
+
+static inline struct bam_chan *to_bam_chan(struct dma_chan *common)
+{
+ return container_of(common, struct bam_chan, vc.chan);
+}
+
+struct bam_device {
+ void __iomem *regs;
+ struct device *dev;
+ struct dma_device common;
+ struct device_dma_parameters dma_parms;
+ struct bam_chan *channels;
+ u32 num_channels;
+
+ /* execution environment ID, from DT */
+ u32 ee;
+
+ struct clk *bamclk;
+ int irq;
+
+ /* dma start transaction tasklet */
+ struct tasklet_struct task;
+};
+
+/**
+ * bam_reset_channel - Reset individual BAM DMA channel
+ * @bchan: bam channel
+ *
+ * This function resets a specific BAM channel
+ */
+static void bam_reset_channel(struct bam_chan *bchan)
+{
+ struct bam_device *bdev = bchan->bdev;
+
+ /* reset channel */
+ writel_relaxed(1, bdev->regs + BAM_P_RST(bchan->id));
+ writel_relaxed(0, bdev->regs + BAM_P_RST(bchan->id));
+
+ /* don't allow reorder of the channel reset */
+ wmb();
+
+ /* make sure hw is initialized when channel is used the first time */
+ bchan->initialized = 0;
+}
+
+/**
+ * bam_chan_init_hw - Initialize channel hardware
+ * @bchan: bam channel
+ *
+ * This function resets and initializes the BAM channel
+ */
+static void bam_chan_init_hw(struct bam_chan *bchan,
+ enum dma_transfer_direction dir)
+{
+ struct bam_device *bdev = bchan->bdev;
+ u32 val;
+
+ /* Reset the channel to clear internal state of the FIFO */
+ bam_reset_channel(bchan);
+
+ /*
+ * write out 8 byte aligned address. We have enough space for this
+ * because we allocated 1 more descriptor (8 bytes) than we can use
+ */
+ writel_relaxed(ALIGN(bchan->fifo_phys, sizeof(struct bam_desc_hw)),
+ bdev->regs + BAM_P_DESC_FIFO_ADDR(bchan->id));
+ writel_relaxed(BAM_DESC_FIFO_SIZE, bdev->regs +
+ BAM_P_FIFO_SIZES(bchan->id));
+
+ /* enable the per pipe interrupts, enable EOT, ERR, and INT irqs */
+ writel_relaxed(P_DEFAULT_IRQS_EN, bdev->regs + BAM_P_IRQ_EN(bchan->id));
+
+ /* unmask the specific pipe and EE combo */
+ val = readl_relaxed(bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee));
+ val |= BIT(bchan->id);
+ writel_relaxed(val, bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee));
+
+ /* set fixed direction and mode, then enable channel */
+ val = P_EN | P_SYS_MODE;
+ if (dir == DMA_DEV_TO_MEM)
+ val |= P_DIRECTION;
+
+ /* make sure the other stores occur before enabling channel */
+ wmb();
+ writel_relaxed(val, bdev->regs + BAM_P_CTRL(bchan->id));
+
+ bchan->initialized = 1;
+
+ /* init FIFO pointers */
+ bchan->head = 0;
+ bchan->tail = 0;
+}
+
+/**
+ * bam_alloc_chan - Allocate channel resources for DMA channel.
+ * @chan: specified channel
+ *
+ * This function allocates the FIFO descriptor memory
+ */
+static int bam_alloc_chan(struct dma_chan *chan)
+{
+ struct bam_chan *bchan = to_bam_chan(chan);
+ struct bam_device *bdev = bchan->bdev;
+
+ /* allocate FIFO descriptor space, but only if necessary */
+ if (!bchan->fifo_virt) {
+ bchan->fifo_virt = dma_alloc_writecombine(bdev->dev,
+ BAM_DESC_FIFO_SIZE, &bchan->fifo_phys,
+ GFP_KERNEL);
+
+ if (!bchan->fifo_virt) {
+ dev_err(bdev->dev, "Failed to allocate desc fifo\n");
+ return -ENOMEM;
+ }
+ }
+
+ return BAM_DESC_FIFO_SIZE;
+}
+
+/**
+ * bam_free_chan - Frees dma resources associated with specific channel
+ * @chan: specified channel
+ *
+ * Free the allocated fifo descriptor memory and channel resources
+ *
+ */
+static void bam_free_chan(struct dma_chan *chan)
+{
+ struct bam_chan *bchan = to_bam_chan(chan);
+ struct bam_device *bdev = bchan->bdev;
+ u32 val;
+
+ vchan_free_chan_resources(to_virt_chan(chan));
+
+ if (bchan->curr_txd) {
+ dev_err(bchan->bdev->dev, "Cannot free busy channel\n");
+ return;
+ }
+
+ bam_reset_channel(bchan);
+
+ dma_free_writecombine(bdev->dev, BAM_DESC_FIFO_SIZE, bchan->fifo_virt,
+ bchan->fifo_phys);
+ bchan->fifo_virt = NULL;
+
+ /* mask irq for pipe/channel */
+ val = readl_relaxed(bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee));
+ val &= ~BIT(bchan->id);
+ writel_relaxed(val, bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee));
+
+ /* disable irq */
+ writel_relaxed(0, bdev->regs + BAM_P_IRQ_EN(bchan->id));
+}
+
+/**
+ * bam_slave_config - set slave configuration for channel
+ * @chan: dma channel
+ * @cfg: slave configuration
+ *
+ * Sets slave configuration for channel
+ *
+ */
+static void bam_slave_config(struct bam_chan *bchan,
+ struct dma_slave_config *cfg)
+{
+ struct bam_device *bdev = bchan->bdev;
+ u32 maxburst;
+
+ if (bchan->slave.direction == DMA_DEV_TO_MEM)
+ maxburst = bchan->slave.src_maxburst = cfg->src_maxburst;
+ else
+ maxburst = bchan->slave.dst_maxburst = cfg->dst_maxburst;
+
+ /* set desc threshold */
+ writel_relaxed(maxburst, bdev->regs + BAM_DESC_CNT_TRSHLD);
+}
+
+/**
+ * bam_prep_slave_sg - Prep slave sg transaction
+ *
+ * @chan: dma channel
+ * @sgl: scatter gather list
+ * @sg_len: length of sg
+ * @direction: DMA transfer direction
+ * @flags: DMA flags
+ * @context: transfer context (unused)
+ */
+static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan,
+ struct scatterlist *sgl, unsigned int sg_len,
+ enum dma_transfer_direction direction, unsigned long flags,
+ void *context)
+{
+ struct bam_chan *bchan = to_bam_chan(chan);
+ struct bam_device *bdev = bchan->bdev;
+ struct bam_async_desc *async_desc;
+ struct scatterlist *sg;
+ u32 i;
+ struct bam_desc_hw *desc;
+
+
+ if (!is_slave_direction(direction)) {
+ dev_err(bdev->dev, "invalid dma direction\n");
+ return NULL;
+ }
+
+
+ /* allocate enough room to accomodate the number of entries */
+ async_desc = kzalloc(sizeof(*async_desc) +
+ (sg_len * sizeof(struct bam_desc_hw)), GFP_NOWAIT);
+
+ if (!async_desc) {
+ dev_err(bdev->dev, "failed to allocate async descriptor\n");
+ goto err_out;
+ }
+
+ async_desc->num_desc = sg_len;
+ async_desc->curr_desc = async_desc->desc;
+ async_desc->dir = direction;
+
+ /* fill in descriptors, align hw descriptor to 8 bytes */
+ desc = async_desc->desc;
+ for_each_sg(sgl, sg, sg_len, i) {
+ if (sg_dma_len(sg) > BAM_MAX_DATA_SIZE) {
+ dev_err(bdev->dev, "segment exceeds max size\n");
+ goto err_out;
+ }
+
+ desc->addr = sg_dma_address(sg);
+ desc->size = sg_dma_len(sg);
+ async_desc->length += sg_dma_len(sg);
+ desc++;
+ }
+
+ return vchan_tx_prep(&bchan->vc, &async_desc->vd, flags);
+
+err_out:
+ kfree(async_desc);
+ return NULL;
+}
+
+/**
+ * bam_dma_terminate_all - terminate all transactions on a channel
+ * @bchan: bam dma channel
+ *
+ * Dequeues and frees all transactions
+ * No callbacks are done
+ *
+ */
+static void bam_dma_terminate_all(struct bam_chan *bchan)
+{
+ unsigned long flag;
+ LIST_HEAD(head);
+
+ /* remove all transactions, including active transaction */
+ spin_lock_irqsave(&bchan->vc.lock, flag);
+ if (bchan->curr_txd) {
+ list_add(&bchan->curr_txd->vd.node, &bchan->vc.desc_issued);
+ bchan->curr_txd = NULL;
+ }
+
+ vchan_get_all_descriptors(&bchan->vc, &head);
+ spin_unlock_irqrestore(&bchan->vc.lock, flag);
+
+ vchan_dma_desc_free_list(&bchan->vc, &head);
+}
+
+/**
+ * bam_control - DMA device control
+ * @chan: dma channel
+ * @cmd: control cmd
+ * @arg: cmd argument
+ *
+ * Perform DMA control command
+ *
+ */
+static int bam_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+ unsigned long arg)
+{
+ struct bam_chan *bchan = to_bam_chan(chan);
+ struct bam_device *bdev = bchan->bdev;
+ int ret = 0;
+ unsigned long flag;
+
+ switch (cmd) {
+ case DMA_PAUSE:
+ spin_lock_irqsave(&bchan->vc.lock, flag);
+ writel_relaxed(1, bdev->regs + BAM_P_HALT(bchan->id));
+ bchan->paused = 1;
+ spin_unlock_irqrestore(&bchan->vc.lock, flag);
+ break;
+ case DMA_RESUME:
+ spin_lock_irqsave(&bchan->vc.lock, flag);
+ writel_relaxed(0, bdev->regs + BAM_P_HALT(bchan->id));
+ bchan->paused = 0;
+ spin_unlock_irqrestore(&bchan->vc.lock, flag);
+ break;
+ case DMA_TERMINATE_ALL:
+ bam_dma_terminate_all(bchan);
+ break;
+ case DMA_SLAVE_CONFIG:
+ bam_slave_config(bchan, (struct dma_slave_config *)arg);
+ break;
+ default:
+ ret = -ENXIO;
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * process_channel_irqs - processes the channel interrupts
+ * @bdev: bam controller
+ *
+ * This function processes the channel interrupts
+ *
+ */
+static u32 process_channel_irqs(struct bam_device *bdev)
+{
+ u32 i, srcs, pipe_stts;
+ unsigned long flags;
+ struct bam_async_desc *async_desc;
+
+ srcs = readl_relaxed(bdev->regs + BAM_IRQ_SRCS_EE(bdev->ee));
+
+ /* return early if no pipe/channel interrupts are present */
+ if (!(srcs & P_IRQ))
+ return srcs;
+
+ for (i = 0; i < bdev->num_channels; i++) {
+ struct bam_chan *bchan = &bdev->channels[i];
+ if (srcs & BIT(i)) {
+ /* clear pipe irq */
+ pipe_stts = readl_relaxed(bdev->regs +
+ BAM_P_IRQ_STTS(i));
+
+ writel_relaxed(pipe_stts, bdev->regs +
+ BAM_P_IRQ_CLR(i));
+
+ spin_lock_irqsave(&bchan->vc.lock, flags);
+ async_desc = bchan->curr_txd;
+
+ if (async_desc) {
+ async_desc->num_desc -= async_desc->xfer_len;
+ async_desc->curr_desc += async_desc->xfer_len;
+ bchan->curr_txd = NULL;
+
+ /* manage FIFO */
+ bchan->head += async_desc->xfer_len;
+ bchan->head %= MAX_DESCRIPTORS;
+
+ /*
+ * if complete, process cookie. Otherwise
+ * push back to front of desc_issued so that
+ * it gets restarted by the tasklet
+ */
+ if (!async_desc->num_desc)
+ vchan_cookie_complete(&async_desc->vd);
+ else
+ list_add(&async_desc->vd.node,
+ &bchan->vc.desc_issued);
+ }
+
+ spin_unlock_irqrestore(&bchan->vc.lock, flags);
+ }
+ }
+
+ return srcs;
+}
+
+/**
+ * bam_dma_irq - irq handler for bam controller
+ * @irq: IRQ of interrupt
+ * @data: callback data
+ *
+ * IRQ handler for the bam controller
+ */
+static irqreturn_t bam_dma_irq(int irq, void *data)
+{
+ struct bam_device *bdev = data;
+ u32 clr_mask = 0, srcs = 0;
+
+ srcs |= process_channel_irqs(bdev);
+
+ /* kick off tasklet to start next dma transfer */
+ if (srcs & P_IRQ)
+ tasklet_schedule(&bdev->task);
+
+ if (srcs & BAM_IRQ)
+ clr_mask = readl_relaxed(bdev->regs + BAM_IRQ_STTS);
+
+ /* don't allow reorder of the various accesses to the BAM registers */
+ mb();
+
+ writel_relaxed(clr_mask, bdev->regs + BAM_IRQ_CLR);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * bam_tx_status - returns status of transaction
+ * @chan: dma channel
+ * @cookie: transaction cookie
+ * @txstate: DMA transaction state
+ *
+ * Return status of dma transaction
+ */
+static enum dma_status bam_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
+ struct dma_tx_state *txstate)
+{
+ struct bam_chan *bchan = to_bam_chan(chan);
+ struct virt_dma_desc *vd;
+ int ret;
+ size_t residue = 0;
+ unsigned int i;
+ unsigned long flags;
+
+ ret = dma_cookie_status(chan, cookie, txstate);
+ if (ret == DMA_COMPLETE)
+ return ret;
+
+ if (!txstate)
+ return bchan->paused ? DMA_PAUSED : ret;
+
+ spin_lock_irqsave(&bchan->vc.lock, flags);
+ vd = vchan_find_desc(&bchan->vc, cookie);
+ if (vd)
+ residue = container_of(vd, struct bam_async_desc, vd)->length;
+ else if (bchan->curr_txd && bchan->curr_txd->vd.tx.cookie == cookie)
+ for (i = 0; i < bchan->curr_txd->num_desc; i++)
+ residue += bchan->curr_txd->curr_desc[i].size;
+
+ spin_unlock_irqrestore(&bchan->vc.lock, flags);
+
+ dma_set_residue(txstate, residue);
+
+ if (ret == DMA_IN_PROGRESS && bchan->paused)
+ ret = DMA_PAUSED;
+
+ return ret;
+}
+
+/**
+ * bam_start_dma - start next transaction
+ * @bchan - bam dma channel
+ *
+ * Note: must hold bam dma channel vc.lock
+ */
+static void bam_start_dma(struct bam_chan *bchan)
+{
+ struct virt_dma_desc *vd = vchan_next_desc(&bchan->vc);
+ struct bam_device *bdev = bchan->bdev;
+ struct bam_async_desc *async_desc;
+ struct bam_desc_hw *desc;
+ struct bam_desc_hw *fifo = PTR_ALIGN(bchan->fifo_virt,
+ sizeof(struct bam_desc_hw));
+
+ if (!vd)
+ return;
+
+ list_del(&vd->node);
+
+ async_desc = container_of(vd, struct bam_async_desc, vd);
+ bchan->curr_txd = async_desc;
+
+ /* on first use, initialize the channel hardware */
+ if (!bchan->initialized)
+ bam_chan_init_hw(bchan, async_desc->dir);
+
+
+ desc = bchan->curr_txd->curr_desc;
+
+ if (async_desc->num_desc > MAX_DESCRIPTORS)
+ async_desc->xfer_len = MAX_DESCRIPTORS;
+ else
+ async_desc->xfer_len = async_desc->num_desc;
+
+ /* set INT on last descriptor */
+ desc[async_desc->xfer_len - 1].flags |= DESC_FLAG_INT;
+
+ if (bchan->tail + async_desc->xfer_len > MAX_DESCRIPTORS) {
+ u32 partial = MAX_DESCRIPTORS - bchan->tail;
+
+ memcpy(&fifo[bchan->tail], desc,
+ partial * sizeof(struct bam_desc_hw));
+ memcpy(fifo, &desc[partial], (async_desc->xfer_len - partial) *
+ sizeof(struct bam_desc_hw));
+ } else {
+ memcpy(&fifo[bchan->tail], desc,
+ async_desc->xfer_len * sizeof(struct bam_desc_hw));
+ }
+
+ bchan->tail += async_desc->xfer_len;
+ bchan->tail %= MAX_DESCRIPTORS;
+
+ /* ensure descriptor writes and dma start not reordered */
+ wmb();
+ writel_relaxed(bchan->tail * sizeof(struct bam_desc_hw),
+ bdev->regs + BAM_P_EVNT_REG(bchan->id));
+}
+
+/**
+ * dma_tasklet - DMA IRQ tasklet
+ * @data: tasklet argument (bam controller structure)
+ *
+ * Sets up next DMA operation and then processes all completed transactions
+ */
+static void dma_tasklet(unsigned long data)
+{
+ struct bam_device *bdev = (struct bam_device *)data;
+ struct bam_chan *bchan;
+ unsigned long flags;
+ unsigned int i;
+
+ /* go through the channels and kick off transactions */
+ for (i = 0; i < bdev->num_channels; i++) {
+ bchan = &bdev->channels[i];
+ spin_lock_irqsave(&bchan->vc.lock, flags);
+
+ if (!list_empty(&bchan->vc.desc_issued) && !bchan->curr_txd)
+ bam_start_dma(bchan);
+ spin_unlock_irqrestore(&bchan->vc.lock, flags);
+ }
+}
+
+/**
+ * bam_issue_pending - starts pending transactions
+ * @chan: dma channel
+ *
+ * Calls tasklet directly which in turn starts any pending transactions
+ */
+static void bam_issue_pending(struct dma_chan *chan)
+{
+ struct bam_chan *bchan = to_bam_chan(chan);
+ unsigned long flags;
+
+ spin_lock_irqsave(&bchan->vc.lock, flags);
+
+ /* if work pending and idle, start a transaction */
+ if (vchan_issue_pending(&bchan->vc) && !bchan->curr_txd)
+ bam_start_dma(bchan);
+
+ spin_unlock_irqrestore(&bchan->vc.lock, flags);
+}
+
+/**
+ * bam_dma_free_desc - free descriptor memory
+ * @vd: virtual descriptor
+ *
+ */
+static void bam_dma_free_desc(struct virt_dma_desc *vd)
+{
+ struct bam_async_desc *async_desc = container_of(vd,
+ struct bam_async_desc, vd);
+
+ kfree(async_desc);
+}
+
+static struct dma_chan *bam_dma_xlate(struct of_phandle_args *dma_spec,
+ struct of_dma *of)
+{
+ struct bam_device *bdev = container_of(of->of_dma_data,
+ struct bam_device, common);
+ unsigned int request;
+
+ if (dma_spec->args_count != 1)
+ return NULL;
+
+ request = dma_spec->args[0];
+ if (request >= bdev->num_channels)
+ return NULL;
+
+ return dma_get_slave_channel(&(bdev->channels[request].vc.chan));
+}
+
+/**
+ * bam_init
+ * @bdev: bam device
+ *
+ * Initialization helper for global bam registers
+ */
+static int bam_init(struct bam_device *bdev)
+{
+ u32 val;
+
+ /* read revision and configuration information */
+ val = readl_relaxed(bdev->regs + BAM_REVISION) & NUM_EES_MASK;
+
+ /* check that configured EE is within range */
+ if (bdev->ee >= val)
+ return -EINVAL;
+
+ val = readl_relaxed(bdev->regs + BAM_NUM_PIPES);
+ bdev->num_channels = val & BAM_NUM_PIPES_MASK;
+
+ /* s/w reset bam */
+ /* after reset all pipes are disabled and idle */
+ val = readl_relaxed(bdev->regs + BAM_CTRL);
+ val |= BAM_SW_RST;
+ writel_relaxed(val, bdev->regs + BAM_CTRL);
+ val &= ~BAM_SW_RST;
+ writel_relaxed(val, bdev->regs + BAM_CTRL);
+
+ /* make sure previous stores are visible before enabling BAM */
+ wmb();
+
+ /* enable bam */
+ val |= BAM_EN;
+ writel_relaxed(val, bdev->regs + BAM_CTRL);
+
+ /* set descriptor threshhold, start with 4 bytes */
+ writel_relaxed(DEFAULT_CNT_THRSHLD, bdev->regs + BAM_DESC_CNT_TRSHLD);
+
+ /* Enable default set of h/w workarounds, ie all except BAM_FULL_PIPE */
+ writel_relaxed(BAM_CNFG_BITS_DEFAULT, bdev->regs + BAM_CNFG_BITS);
+
+ /* enable irqs for errors */
+ writel_relaxed(BAM_ERROR_EN | BAM_HRESP_ERR_EN,
+ bdev->regs + BAM_IRQ_EN);
+
+ return 0;
+}
+
+static void bam_channel_init(struct bam_device *bdev, struct bam_chan *bchan,
+ u32 index)
+{
+ bchan->id = index;
+ bchan->bdev = bdev;
+
+ vchan_init(&bchan->vc, &bdev->common);
+ bchan->vc.desc_free = bam_dma_free_desc;
+}
+
+static int bam_dma_probe(struct platform_device *pdev)
+{
+ struct bam_device *bdev;
+ struct resource *iores;
+ int ret, i;
+
+ bdev = devm_kzalloc(&pdev->dev, sizeof(*bdev), GFP_KERNEL);
+ if (!bdev)
+ return -ENOMEM;
+
+ bdev->dev = &pdev->dev;
+
+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ bdev->regs = devm_ioremap_resource(&pdev->dev, iores);
+ if (IS_ERR(bdev->regs))
+ return PTR_ERR(bdev->regs);
+
+ bdev->irq = platform_get_irq(pdev, 0);
+ if (bdev->irq < 0)
+ return bdev->irq;
+
+ bdev->bamclk = devm_clk_get(bdev->dev, "bam_clk");
+ if (IS_ERR(bdev->bamclk))
+ return PTR_ERR(bdev->bamclk);
+
+ ret = clk_prepare_enable(bdev->bamclk);
+ if (ret) {
+ dev_err(bdev->dev, "failed to prepare/enable clock");
+ return ret;
+ }
+
+ ret = of_property_read_u32(pdev->dev.of_node, "qcom,ee", &bdev->ee);
+ if (ret) {
+ dev_err(bdev->dev, "EE unspecified\n");
+ return ret;
+ }
+
+ ret = bam_init(bdev);
+ if (ret)
+ return ret;
+
+ tasklet_init(&bdev->task, dma_tasklet, (unsigned long)bdev);
+
+ bdev->channels = devm_kcalloc(bdev->dev, bdev->num_channels,
+ sizeof(*bdev->channels), GFP_KERNEL);
+
+ if (!bdev->channels) {
+ ret = -ENOMEM;
+ goto err_disable_clk;
+ }
+
+ /* allocate and initialize channels */
+ INIT_LIST_HEAD(&bdev->common.channels);
+
+ for (i = 0; i < bdev->num_channels; i++)
+ bam_channel_init(bdev, &bdev->channels[i], i);
+
+ ret = devm_request_irq(bdev->dev, bdev->irq, bam_dma_irq,
+ IRQF_TRIGGER_HIGH, "bam_dma", bdev);
+ if (ret)
+ goto err_disable_clk;
+
+ /* set max dma segment size */
+ bdev->common.dev = bdev->dev;
+ bdev->common.dev->dma_parms = &bdev->dma_parms;
+ ret = dma_set_max_seg_size(bdev->common.dev, BAM_MAX_DATA_SIZE);
+ if (ret) {
+ dev_err(bdev->dev, "cannot set maximum segment size\n");
+ goto err_disable_clk;
+ }
+
+ platform_set_drvdata(pdev, bdev);
+
+ /* set capabilities */
+ dma_cap_zero(bdev->common.cap_mask);
+ dma_cap_set(DMA_SLAVE, bdev->common.cap_mask);
+
+ /* initialize dmaengine apis */
+ bdev->common.device_alloc_chan_resources = bam_alloc_chan;
+ bdev->common.device_free_chan_resources = bam_free_chan;
+ bdev->common.device_prep_slave_sg = bam_prep_slave_sg;
+ bdev->common.device_control = bam_control;
+ bdev->common.device_issue_pending = bam_issue_pending;
+ bdev->common.device_tx_status = bam_tx_status;
+ bdev->common.dev = bdev->dev;
+
+ ret = dma_async_device_register(&bdev->common);
+ if (ret) {
+ dev_err(bdev->dev, "failed to register dma async device\n");
+ goto err_disable_clk;
+ }
+
+ ret = of_dma_controller_register(pdev->dev.of_node, bam_dma_xlate,
+ &bdev->common);
+ if (ret)
+ goto err_unregister_dma;
+
+ return 0;
+
+err_unregister_dma:
+ dma_async_device_unregister(&bdev->common);
+err_disable_clk:
+ clk_disable_unprepare(bdev->bamclk);
+ return ret;
+}
+
+static int bam_dma_remove(struct platform_device *pdev)
+{
+ struct bam_device *bdev = platform_get_drvdata(pdev);
+ u32 i;
+
+ of_dma_controller_free(pdev->dev.of_node);
+ dma_async_device_unregister(&bdev->common);
+
+ /* mask all interrupts for this execution environment */
+ writel_relaxed(0, bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee));
+
+ devm_free_irq(bdev->dev, bdev->irq, bdev);
+
+ for (i = 0; i < bdev->num_channels; i++) {
+ bam_dma_terminate_all(&bdev->channels[i]);
+ tasklet_kill(&bdev->channels[i].vc.task);
+
+ dma_free_writecombine(bdev->dev, BAM_DESC_FIFO_SIZE,
+ bdev->channels[i].fifo_virt,
+ bdev->channels[i].fifo_phys);
+ }
+
+ tasklet_kill(&bdev->task);
+
+ clk_disable_unprepare(bdev->bamclk);
+
+ return 0;
+}
+
+static const struct of_device_id bam_of_match[] = {
+ { .compatible = "qcom,bam-v1.4.0", },
+ { .compatible = "qcom,bam-v1.4.1", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, bam_of_match);
+
+static struct platform_driver bam_dma_driver = {
+ .probe = bam_dma_probe,
+ .remove = bam_dma_remove,
+ .driver = {
+ .name = "bam-dma-engine",
+ .owner = THIS_MODULE,
+ .of_match_table = bam_of_match,
+ },
+};
+
+module_platform_driver(bam_dma_driver);
+
+MODULE_AUTHOR("Andy Gross <agross@codeaurora.org>");
+MODULE_DESCRIPTION("QCOM BAM DMA engine driver");
+MODULE_LICENSE("GPL v2");
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply related
* [Patch v5 0/2] Add Qualcomm BAM dmaengine driver
From: Andy Gross @ 2014-02-04 20:42 UTC (permalink / raw)
To: linux-arm-kernel
This patch set introduces the dmaengine driver for the Qualcomm Bus Access
Manager (BAM) DMA controller present on MSM 8x74 devices. A number of the
on-chip devices have their own BAM DMA controller and use it to move data
between system memory and peripherals or between two peripherals.
The initial version of this driver will only support slave DMA operations
between system memory and peripherals.
Changes from v4:
- Add devm_free_irq() to .remove to avoid race condition
- Free FIFO memory in .remove
Changes from v3:
- Remove unused bam_channel_dir.
- Remove incorrect write to BAM_IRQ_SRCS_EE (read only).
- Remove dma direction from DT binding and revise driver to use
direction from prep_slave_sg.
- Remove unnecessary channel reset from channel_init. This could affect
channels controlled from other execution environments.
- Change terminate_all to also take care of the current active
descriptor.
- Rework .remove function to correctly mask interrupts and clean up
resources and tasklets.
Changes from v2:
- Corrected Kconfig dependencies
- Moved execution environment ID to controller DT binding. The EE is
a global setting across all of the channels on the controller.
- Combined header into source file.
- Corrected copyright date.
- Moved channel hardware initialization to occur when channel is used
for the first time.
- Converted dma_alloc_coherent to dma_alloc_writecombine
- Removed unecessary reset of channel from the dma terminate_all
- Corrected usage of EE in irq handler and channel configuration
functions.
- Changed resource functions inside probe to use correct APIs.
- Removed dma filter function and modified dma_xlate to use
dma_get_slave_channel API
- Fixed various nit comments
Changes from v1:
- Converted driver to use virt-dma
- Reworked probe function per review comments
- tx_status function now computes and returns residuals
- Removed proprietary slave config. Removed associated include file.
- Renamed files to reflect vendor name instead of specific device
- Converted to use (readl|writel)_relaxed w/ appropriate barriers
- Removed unions in favor of standard types.
Andy Gross (2):
dmaengine: add Qualcomm BAM dma driver
dmaengine: qcom_bam_dma: Add device tree binding
.../devicetree/bindings/dma/qcom_bam_dma.txt | 48 +
drivers/dma/Kconfig | 9 +
drivers/dma/Makefile | 1 +
drivers/dma/qcom_bam_dma.c | 1066 ++++++++++++++++++++
4 files changed, 1124 insertions(+)
create mode 100644 Documentation/devicetree/bindings/dma/qcom_bam_dma.txt
create mode 100644 drivers/dma/qcom_bam_dma.c
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply
* [PATCH v3 5/7] clocksource/cadence_ttc: Use only one counter
From: Thomas Gleixner @ 2014-02-04 20:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391466877-28908-6-git-send-email-soren.brinkmann@xilinx.com>
On Mon, 3 Feb 2014, Soren Brinkmann wrote:
> Currently the driver uses two of the three counters the TTC provides to
> implement a clocksource and a clockevent device. By using the TTC's
> match feature we can implement both use cases using a single counter
> only.
Are you entirely sure that this match feature is free of the infamous
HPET match feature issues?
See arch/x86/kernel/hpet.c: hpet_next_event()
If yes, please add a comment. If no ....
Thanks,
tglx
^ permalink raw reply
* [PATCH] ARM: ux500: disable msp2 device tree node
From: Lee Jones @ 2014-02-04 20:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391544372-16863-1-git-send-email-linus.walleij@linaro.org>
On Tue, 04 Feb 2014, Linus Walleij wrote:
> Commit 70b41abc151f9
> "ARM: ux500: move MSP pin control to the device tree"
> accidentally activated MSP2, giving rise to a boot scroll
> scream as the kernel attempts to probe a driver for it and
> fails to obtain DMA channel 14.
>
> Fix this up by marking the node disabled again.
>
> Cc: Lee Jones <lee.jones@linaro.org>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> arch/arm/boot/dts/ste-href.dtsi | 1 -
> 1 file changed, 1 deletion(-)
Acked-by: Lee Jones <lee.jones@linaro.org>
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* [PATCH] ARM: at91: add Atmel's SAMA5D3 Xplained board
From: Ludovic Desroches @ 2014-02-04 20:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391535767-30749-1-git-send-email-nicolas.ferre@atmel.com>
On Tue, Feb 04, 2014 at 06:42:47PM +0100, Nicolas Ferre wrote:
> Add DT file for new SAMA5D3 Xpained board.
> This board is based on Atmel's SAMA5D36 Cortex-A5 SoC.
>
You may also add the board to the Makefile.
Ludovic
> Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
> ---
> arch/arm/boot/dts/at91-sama5d3_xplained.dts | 233 ++++++++++++++++++++++++++++
> 1 file changed, 233 insertions(+)
> create mode 100644 arch/arm/boot/dts/at91-sama5d3_xplained.dts
>
> diff --git a/arch/arm/boot/dts/at91-sama5d3_xplained.dts b/arch/arm/boot/dts/at91-sama5d3_xplained.dts
> new file mode 100644
> index 000000000000..fb1349ca60a4
> --- /dev/null
> +++ b/arch/arm/boot/dts/at91-sama5d3_xplained.dts
> @@ -0,0 +1,233 @@
> +/*
> + * at91-sama5d3_xplained.dts - Device Tree file for the SAMA5D3 Xplained board
> + *
> + * Copyright (C) 2014 Atmel,
> + * 2014 Nicolas Ferre <nicolas.ferre@atmel.com>
> + *
> + * Licensed under GPLv2 or later.
> + */
> +/dts-v1/;
> +#include "sama5d36.dtsi"
> +
> +/ {
> + model = "SAMA5D3 Xplained";
> + compatible = "atmel,sama5d3-xplained", "atmel,sama5d3", "atmel,sama5";
> +
> + chosen {
> + bootargs = "console=ttyS0,115200";
> + };
> +
> + memory {
> + reg = <0x20000000 0x10000000>;
> + };
> +
> + ahb {
> + apb {
> + mmc0: mmc at f0000000 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&pinctrl_mmc0_clk_cmd_dat0 &pinctrl_mmc0_dat1_3 &pinctrl_mmc0_dat4_7 &pinctrl_mmc0_cd>;
> + status = "okay";
> + slot at 0 {
> + reg = <0>;
> + bus-width = <8>;
> + cd-gpios = <&pioE 0 GPIO_ACTIVE_LOW>;
> + };
> + };
> +
> + spi0: spi at f0004000 {
> + cs-gpios = <&pioD 13 0>, <0>, <0>, <0>;
> + status = "okay";
> + };
> +
> + can0: can at f000c000 {
> + status = "okay";
> + };
> +
> + i2c0: i2c at f0014000 {
> + status = "okay";
> + };
> +
> + i2c1: i2c at f0018000 {
> + status = "okay";
> + };
> +
> + macb0: ethernet at f0028000 {
> + phy-mode = "rgmii";
> + status = "okay";
> + };
> +
> + usart0: serial at f001c000 {
> + status = "okay";
> + };
> +
> + usart1: serial at f0020000 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&pinctrl_usart1 &pinctrl_usart1_rts_cts>;
> + status = "okay";
> + };
> +
> + uart0: serial at f0024000 {
> + status = "okay";
> + };
> +
> + mmc1: mmc at f8000000 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&pinctrl_mmc1_clk_cmd_dat0 &pinctrl_mmc1_dat1_3 &pinctrl_mmc1_cd>;
> + status = "okay";
> + slot at 0 {
> + reg = <0>;
> + bus-width = <4>;
> + cd-gpios = <&pioE 1 GPIO_ACTIVE_HIGH>;
> + };
> + };
> +
> + spi1: spi at f8008000 {
> + cs-gpios = <&pioC 25 0>, <0>, <0>, <&pioD 16 0>;
> + status = "okay";
> + };
> +
> + adc0: adc at f8018000 {
> + pinctrl-names = "default";
> + pinctrl-0 = <
> + &pinctrl_adc0_adtrg
> + &pinctrl_adc0_ad0
> + &pinctrl_adc0_ad1
> + &pinctrl_adc0_ad2
> + &pinctrl_adc0_ad3
> + &pinctrl_adc0_ad4
> + &pinctrl_adc0_ad5
> + &pinctrl_adc0_ad6
> + &pinctrl_adc0_ad7
> + &pinctrl_adc0_ad8
> + &pinctrl_adc0_ad9
> + >;
> + status = "okay";
> + };
> +
> + i2c2: i2c at f801c000 {
> + dmas = <0>, <0>; /* Do not use DMA for i2c2 */
> + status = "okay";
> + };
> +
> + macb1: ethernet at f802c000 {
> + phy-mode = "rmii";
> + status = "okay";
> + };
> +
> + dbgu: serial at ffffee00 {
> + status = "okay";
> + };
> +
> + pinctrl at fffff200 {
> + board {
> + pinctrl_mmc0_cd: mmc0_cd {
> + atmel,pins =
> + <AT91_PIOE 0 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;
> + };
> +
> + pinctrl_mmc1_cd: mmc1_cd {
> + atmel,pins =
> + <AT91_PIOE 1 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;
> + };
> +
> + pinctrl_usba_vbus: usba_vbus {
> + atmel,pins =
> + <AT91_PIOE 9 AT91_PERIPH_GPIO AT91_PINCTRL_DEGLITCH>; /* PE9, conflicts with A9 */
> + };
> + };
> + };
> +
> + pmc: pmc at fffffc00 {
> + main: mainck {
> + clock-frequency = <12000000>;
> + };
> + };
> + };
> +
> + nand0: nand at 60000000 {
> + nand-bus-width = <8>;
> + nand-ecc-mode = "hw";
> + atmel,has-pmecc;
> + atmel,pmecc-cap = <4>;
> + atmel,pmecc-sector-size = <512>;
> + nand-on-flash-bbt;
> + status = "okay";
> +
> + at91bootstrap at 0 {
> + label = "at91bootstrap";
> + reg = <0x0 0x40000>;
> + };
> +
> + bootloader at 40000 {
> + label = "bootloader";
> + reg = <0x40000 0x80000>;
> + };
> +
> + bootloaderenv at c0000 {
> + label = "bootloader env";
> + reg = <0xc0000 0xc0000>;
> + };
> +
> + dtb at 180000 {
> + label = "device tree";
> + reg = <0x180000 0x80000>;
> + };
> +
> + kernel at 200000 {
> + label = "kernel";
> + reg = <0x200000 0x600000>;
> + };
> +
> + rootfs at 800000 {
> + label = "rootfs";
> + reg = <0x800000 0x0f800000>;
> + };
> + };
> +
> + usb0: gadget at 00500000 {
> + atmel,vbus-gpio = <&pioE 9 GPIO_ACTIVE_HIGH>; /* PE9, conflicts with A9 */
> + pinctrl-names = "default";
> + pinctrl-0 = <&pinctrl_usba_vbus>;
> + status = "okay";
> + };
> +
> + usb1: ohci at 00600000 {
> + num-ports = <3>;
> + atmel,vbus-gpio = <0
> + &pioE 3 GPIO_ACTIVE_LOW
> + &pioE 4 GPIO_ACTIVE_LOW
> + >;
> + status = "okay";
> + };
> +
> + usb2: ehci at 00700000 {
> + status = "okay";
> + };
> + };
> +
> + gpio_keys {
> + compatible = "gpio-keys";
> +
> + bp3 {
> + label = "PB_USER";
> + gpios = <&pioE 29 GPIO_ACTIVE_LOW>;
> + linux,code = <0x104>;
> + gpio-key,wakeup;
> + };
> + };
> +
> + leds {
> + compatible = "gpio-leds";
> +
> + d2 {
> + label = "d2";
> + gpios = <&pioE 23 GPIO_ACTIVE_LOW>; /* PE23, conflicts with A23, CTS2 */
> + linux,default-trigger = "heartbeat";
> + };
> +
> + d3 {
> + label = "d3";
> + gpios = <&pioE 24 GPIO_ACTIVE_HIGH>;
> + };
> + };
> +};
> --
> 1.8.2.2
>
^ permalink raw reply
* [PATCH] ARM: enable IRQs in user undefined instruction vector
From: Kevin Bracey @ 2014-02-04 20:19 UTC (permalink / raw)
To: linux-arm-kernel
If an abort occurs while loading an instruction from user space in
__und_usr, the resulting do_page_fault() can output "sleeping function
called from invalid context" warnings, due to IRQs being disabled in
__und_usr, and hence in do_page_fault().
Avoid the problem by enabling IRQs in __und_usr before attempting to
load the instruction, and modify code and comments in the undefined
instruction handlers to note that IRQs are enabled on entry iff the
instruction was executed in user mode.
See http://comments.gmane.org/gmane.linux.ports.arm.omap/59256 for
an earlier report of the observed might_sleep() warning.
The proposed patch in that thread, which adds a "!irqs_disabled()" test
to do_page_fault(), has already been applied to Android, but that patch
causes an execution failure if another CPU ages the page between the
instruction execution and __und_usr; it prevents do_page_fault() from
attempting to handle the fault and __und_usr's fixup handler is called
instead, but the fixup handler just continues execution from the next
instruction, so the original instruction is silently skipped.
This patch modifies the fixup handler to attempt to re-execute the
original instruction, bringing it in line with the SWI fixup handler;
this also avoids the possibility of the instruction being skipped if
do_page_fault() doesn't handle a fault.
Signed-off-by: Kevin Bracey <kevin@bracey.fi>
---
arch/arm/kernel/entry-armv.S | 11 ++++++++---
arch/arm/mach-ep93xx/crunch-bits.S | 7 ++++++-
arch/arm/vfp/entry.S | 2 +-
3 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index b3fb8c9..bed1567 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -399,6 +399,7 @@ ENDPROC(__irq_usr)
.align 5
__und_usr:
usr_entry
+ enable_irq
mov r2, r4
mov r3, r5
@@ -478,11 +479,14 @@ __und_usr_thumb:
ENDPROC(__und_usr)
/*
- * The out of line fixup for the ldrt instructions above.
+ * The out of line fixup for the ldrt instructions above. Called when there
+ * was an unrecoverable fault accessing the instruction. Attempt to re-execute
+ * the instruction, which should trigger the user fault handling path.
*/
.pushsection .fixup, "ax"
.align 2
-4: mov pc, r9
+4: str r4, [sp, #S_PC]
+ mov pc, r9
.popsection
.pushsection __ex_table,"a"
.long 1b, 4b
@@ -515,7 +519,8 @@ ENDPROC(__und_usr)
* r9 = normal "successful" return address
* r10 = this threads thread_info structure
* lr = unrecognised instruction return address
- * IRQs disabled, FIQs enabled.
+ * IRQs enabled iff the instruction was executed in user mode.
+ * FIQs enabled.
*/
@
@ Fall-through from Thumb-2 __und_usr
diff --git a/arch/arm/mach-ep93xx/crunch-bits.S b/arch/arm/mach-ep93xx/crunch-bits.S
index 0ec9bb4..413d46c 100644
--- a/arch/arm/mach-ep93xx/crunch-bits.S
+++ b/arch/arm/mach-ep93xx/crunch-bits.S
@@ -62,9 +62,14 @@
* r9 = ret_from_exception
* lr = undefined instr exit
*
- * called from prefetch exception handler with interrupts disabled
+ * Called from undefined instruction handler.
+ * Interrupts enabled iff instruction executed in user mode.
*/
ENTRY(crunch_task_enable)
+ mrs r1, cpsr
+ orr r2, r1, #PSR_I_BIT @ disable interrupts
+ msr cpsr_c, r2
+
ldr r8, =(EP93XX_APB_VIRT_BASE + 0x00130000) @ syscon addr
ldr r1, [r8, #0x80]
diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S
index 46e1749..e0e3a00 100644
--- a/arch/arm/vfp/entry.S
+++ b/arch/arm/vfp/entry.S
@@ -19,7 +19,7 @@
@ r9 = normal "successful" return address
@ r10 = this threads thread_info structure
@ lr = unrecognised instruction return address
-@ IRQs disabled.
+@ IRQs enabled iff the instruction was executed in user mode.
@
ENTRY(do_vfp)
#ifdef CONFIG_PREEMPT_COUNT
--
1.8.4.dirty
^ permalink raw reply related
* [PATCH] pinctrl: single: add low powr mode support
From: Linus Walleij @ 2014-02-04 20:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1390893644-3458-1-git-send-email-chao.xie@marvell.com>
On Tue, Jan 28, 2014 at 8:20 AM, Chao Xie <chao.xie@marvell.com> wrote:
> From: Chao Xie <chao.xie@marvell.com>
>
> For some silicons, the pin configuration register can control
> the output of the pin when the pad including the pin enter
> low power mode.
> For example, the pin can be "Drive 1", "Drive 0", "Float" when
> the pad including the pin enter low power mode.
> It is very useful when you want to control the power leakeage
> when the SOC enter low power mode, and can save more power for
> the low power mode.
>
> Signed-off-by: Chao Xie <chao.xie@marvell.com>
Looks similar to the other pin config stuff, patch applied
unless Tony protests.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH v4 1/3] clocksource: timer-keystone: introduce clocksource driver for Keystone
From: Thomas Gleixner @ 2014-02-04 20:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <52F11B5C.40407@ti.com>
On Tue, 4 Feb 2014, Ivan Khoronzhuk wrote:
Please do not top post.
> It was so in v1. But it was decided to use explicit memory barriers,
> because we're always sure the memory barriers are there and that
> they're properly documented. Also in this case I don't need to add
> keystone readl/writel relaxed function variants and to use mixed calls of
> writel/writel_relaxed functions.
>
> See:
> http://www.spinics.net/lists/arm-kernel/msg294941.html
Fair enough, but we want a proper explanation for explicit barriers in
the code and not in some random discussion of patch version X on some
random mailing list.
Aside of that it should be iowmb(), but I might miss something ...
Thanks,
tglx
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox