* Re: [PATCH] KVM: PPC: e500mc: Relax tlb invalidation condition on vcpu schedule
From: Alexander Graf @ 2014-06-12 17:04 UTC (permalink / raw)
To: Mihai Caraman; +Cc: Scott Wood, linuxppc-dev, kvm, kvm-ppc
In-Reply-To: <1402581610-16585-1-git-send-email-mihai.caraman@freescale.com>
On 06/12/2014 04:00 PM, Mihai Caraman wrote:
> On vcpu schedule, the condition checked for tlb pollution is too tight.
> The tlb entries of one vcpu are polluted when a different vcpu from the
> same partition runs in-between. Relax the current tlb invalidation
> condition taking into account the lpid.
>
> Signed-off-by: Mihai Caraman <mihai.caraman <at> freescale.com>
Your mailer is broken? :)
This really should be an @.
I think this should work. Scott, please ack.
Alex
> Cc: Scott Wood <scottwood <at> freescale.com>
> ---
> arch/powerpc/kvm/e500mc.c | 20 +++++++++++++++++---
> 1 file changed, 17 insertions(+), 3 deletions(-)
>
> diff --git a/arch/powerpc/kvm/e500mc.c b/arch/powerpc/kvm/e500mc.c
> index 17e4562..2e0cd69 100644
> --- a/arch/powerpc/kvm/e500mc.c
> +++ b/arch/powerpc/kvm/e500mc.c
> @@ -111,10 +111,12 @@ void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr)
> }
>
> static DEFINE_PER_CPU(struct kvm_vcpu *, last_vcpu_on_cpu);
> +static DEFINE_PER_CPU(int, last_lpid_on_cpu);
>
> static void kvmppc_core_vcpu_load_e500mc(struct kvm_vcpu *vcpu, int cpu)
> {
> struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
> + bool update_last = false, inval_tlb = false;
>
> kvmppc_booke_vcpu_load(vcpu, cpu);
>
> @@ -140,12 +142,24 @@ static void kvmppc_core_vcpu_load_e500mc(struct kvm_vcpu *vcpu, int cpu)
> mtspr(SPRN_GDEAR, vcpu->arch.shared->dar);
> mtspr(SPRN_GESR, vcpu->arch.shared->esr);
>
> - if (vcpu->arch.oldpir != mfspr(SPRN_PIR) ||
> - __get_cpu_var(last_vcpu_on_cpu) != vcpu) {
> - kvmppc_e500_tlbil_all(vcpu_e500);
> + if (vcpu->arch.oldpir != mfspr(SPRN_PIR)) {
> + /* tlb entries deprecated */
> + inval_tlb = update_last = true;
> + } else if (__get_cpu_var(last_vcpu_on_cpu) != vcpu) {
> + update_last = true;
> + /* tlb entries polluted */
> + inval_tlb = __get_cpu_var(last_lpid_on_cpu) ==
> + vcpu->kvm->arch.lpid;
> + }
> +
> + if (update_last) {
> __get_cpu_var(last_vcpu_on_cpu) = vcpu;
> + __get_cpu_var(last_lpid_on_cpu) = vcpu->kvm->arch.lpid;
> }
>
> + if (inval_tlb)
> + kvmppc_e500_tlbil_all(vcpu_e500);
> +
> kvmppc_load_guest_fp(vcpu);
> }
>
^ permalink raw reply
* Re: Device Tree Binding for DSA on P1023RDB
From: Scott Wood @ 2014-06-12 21:21 UTC (permalink / raw)
To: Pannirselvam Kanagaratnam; +Cc: linuxppc-dev
In-Reply-To: <5399C8F2.8060108@xsmail.com>
On Thu, 2014-06-12 at 23:36 +0800, Pannirselvam Kanagaratnam wrote:
> The QORIQ P1023RDB has an option to populate the Marvell 88E6165
> Ethernet switch. We populated this device and was able to initialize
> it as a basic switch in U-Boot. However, the switch driver was not
> loaded upon kernel bootup. DSA kernel config was enabled for the
> 88E6165. The following patch was applied:
>
>
> http://patchwork.ozlabs.org/patch/230257/
>
>
> The switch is attached to phy address 0x3 via dtsec2. My dts file is
> as below. Would appreciate any feedback on whether the DSA is
> correctly structured in the dts.
If you have a dtsec driver you're not working with an upstream kernel
(or you've ported a lot of SDK code to it)... What tree are you working
with? Are there prerequisites to the above patch that you might be
missing?
The above patch is a platform driver and you put the node in the
toplevel device tree node. Have you added marvell,dsa to the list of
compatible strings that get probed (of_device_ids in corenet_generic.c
or an equivalent list in your SDK kernel)?
>
> dsa@0 {
> compatible = "marvell,dsa";
> #address-cells = <2>;
> #size-cells = <0>;
>
> interrupts = <3>;
This interrupts property needs to be four cells rather than one, if MPIC
is the parent -- assuming you have #interrupt-cells = <4> and not some
old device tree with #interrupt-cells = <2>, but in any case you need
more than one cell.
-Scott
^ permalink raw reply
* Re: power and percpu: Could we move the paca into the percpu area?
From: Benjamin Herrenschmidt @ 2014-06-12 21:57 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: Tejun Heo, linuxppc-dev, Christoph Lameter
In-Reply-To: <20140612122639.GA17838@gate.crashing.org>
On Thu, 2014-06-12 at 07:26 -0500, Segher Boessenkool wrote:
> But, indeed, it does look like GCC doesn't use it. It seems to me
> that
> some ABI forbade userland (or non-libraries or whatever) from using
> it.
> I'll see what I can find out.
I can still use -ffixed-cr5 for safety no ?
Cheers,
Ben.
^ permalink raw reply
* Re: powerpc/ppc64: Allow allmodconfig to build (finally !)
From: Benjamin Herrenschmidt @ 2014-06-12 21:57 UTC (permalink / raw)
To: Guenter Roeck; +Cc: linuxppc-dev
In-Reply-To: <20140612122644.GA17249@roeck-us.net>
On Thu, 2014-06-12 at 05:26 -0700, Guenter Roeck wrote:
> what happened with this patch ?
Well it breaks with that binutils version of yours ... I'm trying to fix
it in a better way but it's a mess... still working on it.
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH] powerpc: Add AT_HWCAP2 to indicate V.CRYPTO category support
From: Benjamin Herrenschmidt @ 2014-06-12 22:03 UTC (permalink / raw)
To: Steve Munroe
Cc: linuxppc-dev, Adhemerval Zanella, Michael J Wolf,
Hanns-Joachim Uhl
In-Reply-To: <OF26AC1193.59958340-ON85257CF5.00528030-86257CF5.0053A37D@us.ibm.com>
On Thu, 2014-06-12 at 10:13 -0500, Steve Munroe wrote:
> The precedent we have used is that features that refer to ISA Categories include _HAS_ following the PPC_FEATURE[2]. So GLIBC specifies in hwcap.h:
>
> /* Feature definitions in AT_HWCAP2. */
> #define PPC_FEATURE2_ARCH_2_07 0x80000000 /* ISA 2.07 */
> #define PPC_FEATURE2_HAS_HTM 0x40000000 /* Hardware Transactional
> Memory */
> #define PPC_FEATURE2_HAS_DSCR 0x20000000 /* Data Stream Control
> Register */
> #define PPC_FEATURE2_HAS_EBB 0x10000000 /* Event Base Branching */
> #define PPC_FEATURE2_HAS_ISEL 0x08000000 /* Integer Select */
> #define PPC_FEATURE2_HAS_TAR 0x04000000 /* Target Address Register */
>
> This was carried from the original AT_HWCAP defines.
Off, they don't have the "HAS" in the kernel definitions...
> $ grep _HAS_ ./sysdeps/powerpc/bits/hwcap.h
> #define PPC_FEATURE_HAS_ALTIVEC 0x10000000 /* SIMD/Vector Unit. */
> #define PPC_FEATURE_HAS_FPU 0x08000000 /* Floating Point Unit. */
> #define PPC_FEATURE_HAS_MMU 0x04000000 /* Memory Management Unit. */
> #define PPC_FEATURE_HAS_4xxMAC 0x02000000 /* 4xx Multiply Accumulator. */
> #define PPC_FEATURE_HAS_SPE 0x00800000 /* Signal Processing ext. */
> #define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000 /* SPE Float. */
> #define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000 /* SPE Double. */
> #define PPC_FEATURE_HAS_DFP 0x00000400 /* Decimal FP Unit */
> #define PPC_FEATURE_HAS_VSX 0x00000080 /* P7 Vector Extension. */
>
> So could we agree on PPC_FEATURE2_HAS_VEC_CRYPTO or the shorter PPC_FEATURE2_HAS_VCRYPTO?
Well, I made it consistent with the other HWCAP2 bits exposed by the
kernel which seem to differ from the glibc versions :-(
In any case, I've merged it but I can do a follow up patch that adds
the _HAS_ everywhere, hopefully nobody in userspace use the kernel
definition and they use the glibc one instead.
In that case, go for VCRYPTO.
Cheers,
Ben.
> Steven J. Munroe
> Linux on Power Toolchain Architect
> IBM Corporation, Linux Technology Center
>
>
> Inactive hide details for Benjamin Herrenschmidt ---06/10/2014 12:05:07 AM---The Vector Crypto category instructions are supporBenjamin Herrenschmidt ---06/10/2014 12:05:07 AM---The Vector Crypto category instructions are supported by current POWER8 chips, advertise them to use
>
> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> To: linuxppc-dev@ozlabs.org
> Cc: Steve Munroe/Rochester/IBM@IBMUS, Hanns-Joachim Uhl <hannsj_uhl@de.ibm.com>, Diane Brent/Poughkeepsie/IBM@IBMUS, Jeffrey Scheel/Rochester/IBM@IBMUS, Adhemerval Zanella <azanella@linux.vnet.ibm.com>
> Date: 06/10/2014 12:05 AM
> Subject: [PATCH] powerpc: Add AT_HWCAP2 to indicate V.CRYPTO category support
>
>
>
> ______________________________________________________________________
>
>
>
> The Vector Crypto category instructions are supported by current POWER8
> chips, advertise them to userspace using a specific bit to properly
> differentiate with chips of the same architecture level that might not
> have them.
>
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> CC: <stable@vger.kernel.org> [v3.10+]
> --
>
> diff --git a/arch/powerpc/include/uapi/asm/cputable.h b/arch/powerpc/include/uapi/asm/cputable.h
> index 5b76579..de2c0e4 100644
> --- a/arch/powerpc/include/uapi/asm/cputable.h
> +++ b/arch/powerpc/include/uapi/asm/cputable.h
> @@ -41,5 +41,6 @@
> #define PPC_FEATURE2_EBB 0x10000000
> #define PPC_FEATURE2_ISEL 0x08000000
> #define PPC_FEATURE2_TAR 0x04000000
> +#define PPC_FEATURE2_VEC_CRYPTO 0x02000000
>
> #endif /* _UAPI__ASM_POWERPC_CPUTABLE_H */
> diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
> index c1faade..11da04a 100644
> --- a/arch/powerpc/kernel/cputable.c
> +++ b/arch/powerpc/kernel/cputable.c
> @@ -109,7 +109,8 @@ extern void __restore_cpu_e6500(void);
> PPC_FEATURE_PSERIES_PERFMON_COMPAT)
> #define COMMON_USER2_POWER8 (PPC_FEATURE2_ARCH_2_07 | \
> PPC_FEATURE2_HTM_COMP | PPC_FEATURE2_DSCR | \
> - PPC_FEATURE2_ISEL | PPC_FEATURE2_TAR)
> + PPC_FEATURE2_ISEL | PPC_FEATURE2_TAR | \
> + PPC_FEATURE2_VEC_CRYPTO)
> #define COMMON_USER_PA6T (COMMON_USER_PPC64 | PPC_FEATURE_PA6T |\
> PPC_FEATURE_TRUE_LE | \
> PPC_FEATURE_HAS_ALTIVEC_COMP)
>
>
>
^ permalink raw reply
* Re: power and percpu: Could we move the paca into the percpu area?
From: Segher Boessenkool @ 2014-06-12 22:15 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: Tejun Heo, linuxppc-dev, Christoph Lameter
In-Reply-To: <1402610228.14780.84.camel@pasglop>
On Fri, Jun 13, 2014 at 07:57:08AM +1000, Benjamin Herrenschmidt wrote:
> On Thu, 2014-06-12 at 07:26 -0500, Segher Boessenkool wrote:
> > But, indeed, it does look like GCC doesn't use it. It seems to me
> > that
> > some ABI forbade userland (or non-libraries or whatever) from using
> > it.
> > I'll see what I can find out.
>
> I can still use -ffixed-cr5 for safety no ?
Yes, definitely, and in fact you have to if GCC changes to not have cr5
fixed by default (which may or may not happen). It will be good
documentation in either case :-)
Segher
^ permalink raw reply
* Re: powerpc/ppc64: Allow allmodconfig to build (finally !)
From: Guenter Roeck @ 2014-06-12 22:17 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1402610268.14780.85.camel@pasglop>
On 06/12/2014 02:57 PM, Benjamin Herrenschmidt wrote:
> On Thu, 2014-06-12 at 05:26 -0700, Guenter Roeck wrote:
>> what happened with this patch ?
>
> Well it breaks with that binutils version of yours ... I'm trying to fix
> it in a better way but it's a mess... still working on it.
>
I updated my binutils since then, though, and the other problem I encountered
(with the changed ABI) has been fixed. As it is, I'd prefer to have the patch
applied, but I can understand if you don't want to apply it in case others
hit the problem I had.
Guenter
^ permalink raw reply
* [git pull] Please pull powerpc.git next branch
From: Benjamin Herrenschmidt @ 2014-06-13 0:55 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linuxppc-dev, Linux Kernel list
Hi Linus !
Here are the remaining bits I was mentioning earlier. Mostly bug fixes
and new selftests from Michael (yay !). He also removed the WSP platform
and A2 core support which were dead before release, so less clutter.
One little "feature" I snuck in is the doorbell IPI support for
non-virtualized P8 which speeds up IPIs significantly between threads
of a core.
Cheers,
Ben.
The following changes since commit dfb945473ae8528fd885607b6fa843c676745e0c:
Merge git://www.linux-watchdog.org/linux-watchdog (2014-06-10 19:16:36 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git next
for you to fetch changes up to ad718622ab6d500c870772b1b8dda46fa2195e6d:
powerpc/book3s: Fix some ABIv2 issues in machine check code (2014-06-12 09:41:33 +1000)
----------------------------------------------------------------
Anton Blanchard (4):
powernv: Fix permissions on sysparam sysfs entries
crypto/nx: disable NX on little endian builds
powerpc/powernv: Reduce panic timeout from 180s to 10s
powerpc/book3s: Fix some ABIv2 issues in machine check code
Benjamin Herrenschmidt (1):
powerpc: Add AT_HWCAP2 to indicate V.CRYPTO category support
Dan Carpenter (2):
powerpc/cpm: Remove duplicate FCC_GFMR_TTX define
powerpc/spufs: Remove duplicate SPUFS_CNTL_MAP_SIZE define
Gavin Shan (5):
powerpc/eeh: Clear frozen state for child PE
powerpc/eeh: Report frozen parent PE prior to child PE
powerpc/powernv: Don't escalate non-existing frozen PE
powerpc/powernv: Fix killed EEH event
powerpc/eeh: Dump PE location code
Guo Chao (1):
powerpc/powernv: Fix endianness problems in EEH
Joel Stanley (1):
powerpc/powernv: Fix reading of OPAL msglog
Kees Cook (1):
powerpc/xmon: avoid format string leaking to printk
Mahesh Salgaonkar (4):
powerpc/book3s: Fix machine check handling for unhandled errors
powerpc/book3s: Add stack overflow check in machine check handler.
powerpc/book3s: Increment the mce counter during machine_check_early call.
powerpc/book3s: Fix guest MC delivery mechanism to avoid soft lockups in guest.
Michael Ellerman (6):
powerpc: Remove platforms/wsp and associated pieces
powerpc/perf: Ensure all EBB register state is cleared on fork()
selftests/powerpc: Fix instruction loop for ABIv2 (LE)
selftests/powerpc: Put the test in a separate process group
selftests/powerpc: Add support for skipping tests
selftests/powerpc: Add tests of PMU EBBs
Michael Neuling (3):
powerpc: Don't setup CPUs with bad status
powerpc/cpuidle: Only clear LPCR decrementer wakeup bit on fast sleep entry
powerpc/powernv: Enable POWER8 doorbell IPIs
Paul Bolle (3):
powerpc: Remove check for CONFIG_SERIAL_TEXT_DEBUG
powerpc: fix typo 'CONFIG_PPC_CPU'
powerpc: fix typo 'CONFIG_PMAC'
Sam bobroff (1):
powerpc: Correct DSCR during TM context switch
Shreyas B. Prabhu (2):
powerpc/powernv: Include asm/smp.h to fix UP build failure
powerpc/powernv : Disable subcore for UP configs
arch/powerpc/Kconfig.debug | 5 -
arch/powerpc/configs/chroma_defconfig | 307 ------
arch/powerpc/include/asm/cpm2.h | 1 -
arch/powerpc/include/asm/eeh.h | 1 +
arch/powerpc/include/asm/eeh_event.h | 2 +-
arch/powerpc/include/asm/mmu-book3e.h | 4 -
arch/powerpc/include/asm/opal.h | 102 +-
arch/powerpc/include/asm/reg_a2.h | 9 -
arch/powerpc/include/asm/switch_to.h | 8 +-
arch/powerpc/include/asm/wsp.h | 14 -
arch/powerpc/include/uapi/asm/cputable.h | 1 +
arch/powerpc/kernel/Makefile | 1 -
arch/powerpc/kernel/cpu_setup_a2.S | 120 ---
arch/powerpc/kernel/cpu_setup_power.S | 2 +
arch/powerpc/kernel/cputable.c | 41 +-
arch/powerpc/kernel/eeh.c | 38 +-
arch/powerpc/kernel/eeh_driver.c | 24 +-
arch/powerpc/kernel/eeh_event.c | 21 +-
arch/powerpc/kernel/eeh_pe.c | 60 ++
arch/powerpc/kernel/entry_64.S | 6 -
arch/powerpc/kernel/exceptions-64e.S | 16 -
arch/powerpc/kernel/exceptions-64s.S | 64 +-
arch/powerpc/kernel/head_40x.S | 19 -
arch/powerpc/kernel/process.c | 8 +-
arch/powerpc/kernel/setup-common.c | 2 +-
arch/powerpc/kernel/time.c | 2 +-
arch/powerpc/kernel/traps.c | 2 +
arch/powerpc/kernel/udbg.c | 2 -
arch/powerpc/kernel/udbg_16550.c | 11 -
arch/powerpc/kvm/book3s_hv_ras.c | 15 +-
arch/powerpc/kvm/book3s_hv_rmhandlers.S | 19 +-
arch/powerpc/lib/sstep.c | 2 +-
arch/powerpc/platforms/Kconfig | 1 -
arch/powerpc/platforms/Kconfig.cputype | 6 +-
arch/powerpc/platforms/Makefile | 1 -
arch/powerpc/platforms/cell/spufs/spufs.h | 1 -
arch/powerpc/platforms/powernv/Kconfig | 1 +
arch/powerpc/platforms/powernv/Makefile | 4 +-
arch/powerpc/platforms/powernv/eeh-ioda.c | 109 +-
arch/powerpc/platforms/powernv/opal-msglog.c | 6 +-
arch/powerpc/platforms/powernv/opal-sysparam.c | 4 +-
arch/powerpc/platforms/powernv/pci.c | 81 +-
arch/powerpc/platforms/powernv/setup.c | 3 +
arch/powerpc/platforms/powernv/smp.c | 6 +
arch/powerpc/platforms/pseries/Kconfig | 1 +
arch/powerpc/platforms/wsp/Kconfig | 30 -
arch/powerpc/platforms/wsp/Makefile | 10 -
arch/powerpc/platforms/wsp/chroma.c | 56 -
arch/powerpc/platforms/wsp/h8.c | 135 ---
arch/powerpc/platforms/wsp/ics.c | 762 -------------
arch/powerpc/platforms/wsp/ics.h | 25 -
arch/powerpc/platforms/wsp/msi.c | 102 --
arch/powerpc/platforms/wsp/msi.h | 19 -
arch/powerpc/platforms/wsp/opb_pic.c | 321 ------
arch/powerpc/platforms/wsp/psr2.c | 67 --
arch/powerpc/platforms/wsp/scom_smp.c | 435 --------
arch/powerpc/platforms/wsp/scom_wsp.c | 82 --
arch/powerpc/platforms/wsp/setup.c | 36 -
arch/powerpc/platforms/wsp/smp.c | 88 --
arch/powerpc/platforms/wsp/wsp.c | 117 --
arch/powerpc/platforms/wsp/wsp.h | 29 -
arch/powerpc/platforms/wsp/wsp_pci.c | 1134 --------------------
arch/powerpc/platforms/wsp/wsp_pci.h | 268 -----
arch/powerpc/sysdev/xics/icp-native.c | 9 +-
arch/powerpc/xmon/nonstdio.c | 2 +-
drivers/cpuidle/cpuidle-powernv.c | 8 +-
drivers/crypto/Kconfig | 2 +-
tools/testing/selftests/powerpc/Makefile | 2 +-
tools/testing/selftests/powerpc/harness.c | 15 +-
tools/testing/selftests/powerpc/pmu/Makefile | 26 +-
tools/testing/selftests/powerpc/pmu/ebb/Makefile | 32 +
.../powerpc/pmu/ebb/back_to_back_ebbs_test.c | 106 ++
.../powerpc/pmu/ebb/close_clears_pmcc_test.c | 59 +
.../powerpc/pmu/ebb/cpu_event_pinned_vs_ebb_test.c | 93 ++
.../powerpc/pmu/ebb/cpu_event_vs_ebb_test.c | 89 ++
.../selftests/powerpc/pmu/ebb/cycles_test.c | 58 +
.../powerpc/pmu/ebb/cycles_with_freeze_test.c | 117 ++
tools/testing/selftests/powerpc/pmu/ebb/ebb.c | 727 +++++++++++++
tools/testing/selftests/powerpc/pmu/ebb/ebb.h | 78 ++
.../selftests/powerpc/pmu/ebb/ebb_handler.S | 365 +++++++
.../selftests/powerpc/pmu/ebb/ebb_on_child_test.c | 86 ++
.../powerpc/pmu/ebb/ebb_on_willing_child_test.c | 92 ++
.../powerpc/pmu/ebb/ebb_vs_cpu_event_test.c | 86 ++
.../powerpc/pmu/ebb/event_attributes_test.c | 131 +++
.../powerpc/pmu/ebb/fixed_instruction_loop.S | 43 +
.../selftests/powerpc/pmu/ebb/fork_cleanup_test.c | 79 ++
.../powerpc/pmu/ebb/instruction_count_test.c | 164 +++
.../powerpc/pmu/ebb/lost_exception_test.c | 100 ++
.../selftests/powerpc/pmu/ebb/multi_counter_test.c | 91 ++
.../powerpc/pmu/ebb/multi_ebb_procs_test.c | 109 ++
.../selftests/powerpc/pmu/ebb/no_handler_test.c | 61 ++
.../selftests/powerpc/pmu/ebb/pmae_handling_test.c | 106 ++
.../powerpc/pmu/ebb/pmc56_overflow_test.c | 93 ++
tools/testing/selftests/powerpc/pmu/ebb/reg.h | 49 +
.../selftests/powerpc/pmu/ebb/reg_access_test.c | 39 +
.../pmu/ebb/task_event_pinned_vs_ebb_test.c | 91 ++
.../powerpc/pmu/ebb/task_event_vs_ebb_test.c | 83 ++
tools/testing/selftests/powerpc/pmu/ebb/trace.c | 300 ++++++
tools/testing/selftests/powerpc/pmu/ebb/trace.h | 41 +
tools/testing/selftests/powerpc/pmu/event.c | 26 +
tools/testing/selftests/powerpc/pmu/event.h | 4 +
tools/testing/selftests/powerpc/pmu/lib.c | 252 +++++
tools/testing/selftests/powerpc/pmu/lib.h | 41 +
tools/testing/selftests/powerpc/pmu/loop.S | 73 +-
tools/testing/selftests/powerpc/subunit.h | 5 +
tools/testing/selftests/powerpc/tm/Makefile | 15 +
.../testing/selftests/powerpc/tm/tm-resched-dscr.c | 90 ++
tools/testing/selftests/powerpc/utils.h | 12 +
108 files changed, 4514 insertions(+), 4505 deletions(-)
delete mode 100644 arch/powerpc/configs/chroma_defconfig
delete mode 100644 arch/powerpc/include/asm/wsp.h
delete mode 100644 arch/powerpc/kernel/cpu_setup_a2.S
delete mode 100644 arch/powerpc/platforms/wsp/Kconfig
delete mode 100644 arch/powerpc/platforms/wsp/Makefile
delete mode 100644 arch/powerpc/platforms/wsp/chroma.c
delete mode 100644 arch/powerpc/platforms/wsp/h8.c
delete mode 100644 arch/powerpc/platforms/wsp/ics.c
delete mode 100644 arch/powerpc/platforms/wsp/ics.h
delete mode 100644 arch/powerpc/platforms/wsp/msi.c
delete mode 100644 arch/powerpc/platforms/wsp/msi.h
delete mode 100644 arch/powerpc/platforms/wsp/opb_pic.c
delete mode 100644 arch/powerpc/platforms/wsp/psr2.c
delete mode 100644 arch/powerpc/platforms/wsp/scom_smp.c
delete mode 100644 arch/powerpc/platforms/wsp/scom_wsp.c
delete mode 100644 arch/powerpc/platforms/wsp/setup.c
delete mode 100644 arch/powerpc/platforms/wsp/smp.c
delete mode 100644 arch/powerpc/platforms/wsp/wsp.c
delete mode 100644 arch/powerpc/platforms/wsp/wsp.h
delete mode 100644 arch/powerpc/platforms/wsp/wsp_pci.c
delete mode 100644 arch/powerpc/platforms/wsp/wsp_pci.h
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/Makefile
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/back_to_back_ebbs_test.c
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/close_clears_pmcc_test.c
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/cpu_event_pinned_vs_ebb_test.c
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/cpu_event_vs_ebb_test.c
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/cycles_test.c
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/cycles_with_freeze_test.c
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/ebb.c
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/ebb.h
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/ebb_handler.S
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/ebb_on_child_test.c
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/ebb_on_willing_child_test.c
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/ebb_vs_cpu_event_test.c
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/event_attributes_test.c
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/fixed_instruction_loop.S
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/fork_cleanup_test.c
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/lost_exception_test.c
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/multi_counter_test.c
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/multi_ebb_procs_test.c
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/no_handler_test.c
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/pmae_handling_test.c
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/pmc56_overflow_test.c
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/reg.h
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/task_event_pinned_vs_ebb_test.c
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/task_event_vs_ebb_test.c
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/trace.c
create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/trace.h
create mode 100644 tools/testing/selftests/powerpc/pmu/lib.c
create mode 100644 tools/testing/selftests/powerpc/pmu/lib.h
create mode 100644 tools/testing/selftests/powerpc/tm/Makefile
create mode 100644 tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
^ permalink raw reply
* Re: [git pull] Please pull powerpc.git next branch
From: Benjamin Herrenschmidt @ 2014-06-13 0:56 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linuxppc-dev, Linux Kernel list
In-Reply-To: <1402620918.14780.102.camel@pasglop>
On Fri, 2014-06-13 at 10:55 +1000, Benjamin Herrenschmidt wrote:
> Hi Linus !
Sending a copy via IBM just in case gmail has an issue with pull
requests :-) If it goes through fine I'll stop doing it.
Cheers,
Ben.
> Here are the remaining bits I was mentioning earlier. Mostly bug fixes
> and new selftests from Michael (yay !). He also removed the WSP platform
> and A2 core support which were dead before release, so less clutter.
>
> One little "feature" I snuck in is the doorbell IPI support for
> non-virtualized P8 which speeds up IPIs significantly between threads
> of a core.
>
> Cheers,
> Ben.
>
> The following changes since commit dfb945473ae8528fd885607b6fa843c676745e0c:
>
> Merge git://www.linux-watchdog.org/linux-watchdog (2014-06-10 19:16:36 -0700)
>
> are available in the git repository at:
>
>
> git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git next
>
> for you to fetch changes up to ad718622ab6d500c870772b1b8dda46fa2195e6d:
>
> powerpc/book3s: Fix some ABIv2 issues in machine check code (2014-06-12 09:41:33 +1000)
>
> ----------------------------------------------------------------
> Anton Blanchard (4):
> powernv: Fix permissions on sysparam sysfs entries
> crypto/nx: disable NX on little endian builds
> powerpc/powernv: Reduce panic timeout from 180s to 10s
> powerpc/book3s: Fix some ABIv2 issues in machine check code
>
> Benjamin Herrenschmidt (1):
> powerpc: Add AT_HWCAP2 to indicate V.CRYPTO category support
>
> Dan Carpenter (2):
> powerpc/cpm: Remove duplicate FCC_GFMR_TTX define
> powerpc/spufs: Remove duplicate SPUFS_CNTL_MAP_SIZE define
>
> Gavin Shan (5):
> powerpc/eeh: Clear frozen state for child PE
> powerpc/eeh: Report frozen parent PE prior to child PE
> powerpc/powernv: Don't escalate non-existing frozen PE
> powerpc/powernv: Fix killed EEH event
> powerpc/eeh: Dump PE location code
>
> Guo Chao (1):
> powerpc/powernv: Fix endianness problems in EEH
>
> Joel Stanley (1):
> powerpc/powernv: Fix reading of OPAL msglog
>
> Kees Cook (1):
> powerpc/xmon: avoid format string leaking to printk
>
> Mahesh Salgaonkar (4):
> powerpc/book3s: Fix machine check handling for unhandled errors
> powerpc/book3s: Add stack overflow check in machine check handler.
> powerpc/book3s: Increment the mce counter during machine_check_early call.
> powerpc/book3s: Fix guest MC delivery mechanism to avoid soft lockups in guest.
>
> Michael Ellerman (6):
> powerpc: Remove platforms/wsp and associated pieces
> powerpc/perf: Ensure all EBB register state is cleared on fork()
> selftests/powerpc: Fix instruction loop for ABIv2 (LE)
> selftests/powerpc: Put the test in a separate process group
> selftests/powerpc: Add support for skipping tests
> selftests/powerpc: Add tests of PMU EBBs
>
> Michael Neuling (3):
> powerpc: Don't setup CPUs with bad status
> powerpc/cpuidle: Only clear LPCR decrementer wakeup bit on fast sleep entry
> powerpc/powernv: Enable POWER8 doorbell IPIs
>
> Paul Bolle (3):
> powerpc: Remove check for CONFIG_SERIAL_TEXT_DEBUG
> powerpc: fix typo 'CONFIG_PPC_CPU'
> powerpc: fix typo 'CONFIG_PMAC'
>
> Sam bobroff (1):
> powerpc: Correct DSCR during TM context switch
>
> Shreyas B. Prabhu (2):
> powerpc/powernv: Include asm/smp.h to fix UP build failure
> powerpc/powernv : Disable subcore for UP configs
>
> arch/powerpc/Kconfig.debug | 5 -
> arch/powerpc/configs/chroma_defconfig | 307 ------
> arch/powerpc/include/asm/cpm2.h | 1 -
> arch/powerpc/include/asm/eeh.h | 1 +
> arch/powerpc/include/asm/eeh_event.h | 2 +-
> arch/powerpc/include/asm/mmu-book3e.h | 4 -
> arch/powerpc/include/asm/opal.h | 102 +-
> arch/powerpc/include/asm/reg_a2.h | 9 -
> arch/powerpc/include/asm/switch_to.h | 8 +-
> arch/powerpc/include/asm/wsp.h | 14 -
> arch/powerpc/include/uapi/asm/cputable.h | 1 +
> arch/powerpc/kernel/Makefile | 1 -
> arch/powerpc/kernel/cpu_setup_a2.S | 120 ---
> arch/powerpc/kernel/cpu_setup_power.S | 2 +
> arch/powerpc/kernel/cputable.c | 41 +-
> arch/powerpc/kernel/eeh.c | 38 +-
> arch/powerpc/kernel/eeh_driver.c | 24 +-
> arch/powerpc/kernel/eeh_event.c | 21 +-
> arch/powerpc/kernel/eeh_pe.c | 60 ++
> arch/powerpc/kernel/entry_64.S | 6 -
> arch/powerpc/kernel/exceptions-64e.S | 16 -
> arch/powerpc/kernel/exceptions-64s.S | 64 +-
> arch/powerpc/kernel/head_40x.S | 19 -
> arch/powerpc/kernel/process.c | 8 +-
> arch/powerpc/kernel/setup-common.c | 2 +-
> arch/powerpc/kernel/time.c | 2 +-
> arch/powerpc/kernel/traps.c | 2 +
> arch/powerpc/kernel/udbg.c | 2 -
> arch/powerpc/kernel/udbg_16550.c | 11 -
> arch/powerpc/kvm/book3s_hv_ras.c | 15 +-
> arch/powerpc/kvm/book3s_hv_rmhandlers.S | 19 +-
> arch/powerpc/lib/sstep.c | 2 +-
> arch/powerpc/platforms/Kconfig | 1 -
> arch/powerpc/platforms/Kconfig.cputype | 6 +-
> arch/powerpc/platforms/Makefile | 1 -
> arch/powerpc/platforms/cell/spufs/spufs.h | 1 -
> arch/powerpc/platforms/powernv/Kconfig | 1 +
> arch/powerpc/platforms/powernv/Makefile | 4 +-
> arch/powerpc/platforms/powernv/eeh-ioda.c | 109 +-
> arch/powerpc/platforms/powernv/opal-msglog.c | 6 +-
> arch/powerpc/platforms/powernv/opal-sysparam.c | 4 +-
> arch/powerpc/platforms/powernv/pci.c | 81 +-
> arch/powerpc/platforms/powernv/setup.c | 3 +
> arch/powerpc/platforms/powernv/smp.c | 6 +
> arch/powerpc/platforms/pseries/Kconfig | 1 +
> arch/powerpc/platforms/wsp/Kconfig | 30 -
> arch/powerpc/platforms/wsp/Makefile | 10 -
> arch/powerpc/platforms/wsp/chroma.c | 56 -
> arch/powerpc/platforms/wsp/h8.c | 135 ---
> arch/powerpc/platforms/wsp/ics.c | 762 -------------
> arch/powerpc/platforms/wsp/ics.h | 25 -
> arch/powerpc/platforms/wsp/msi.c | 102 --
> arch/powerpc/platforms/wsp/msi.h | 19 -
> arch/powerpc/platforms/wsp/opb_pic.c | 321 ------
> arch/powerpc/platforms/wsp/psr2.c | 67 --
> arch/powerpc/platforms/wsp/scom_smp.c | 435 --------
> arch/powerpc/platforms/wsp/scom_wsp.c | 82 --
> arch/powerpc/platforms/wsp/setup.c | 36 -
> arch/powerpc/platforms/wsp/smp.c | 88 --
> arch/powerpc/platforms/wsp/wsp.c | 117 --
> arch/powerpc/platforms/wsp/wsp.h | 29 -
> arch/powerpc/platforms/wsp/wsp_pci.c | 1134 --------------------
> arch/powerpc/platforms/wsp/wsp_pci.h | 268 -----
> arch/powerpc/sysdev/xics/icp-native.c | 9 +-
> arch/powerpc/xmon/nonstdio.c | 2 +-
> drivers/cpuidle/cpuidle-powernv.c | 8 +-
> drivers/crypto/Kconfig | 2 +-
> tools/testing/selftests/powerpc/Makefile | 2 +-
> tools/testing/selftests/powerpc/harness.c | 15 +-
> tools/testing/selftests/powerpc/pmu/Makefile | 26 +-
> tools/testing/selftests/powerpc/pmu/ebb/Makefile | 32 +
> .../powerpc/pmu/ebb/back_to_back_ebbs_test.c | 106 ++
> .../powerpc/pmu/ebb/close_clears_pmcc_test.c | 59 +
> .../powerpc/pmu/ebb/cpu_event_pinned_vs_ebb_test.c | 93 ++
> .../powerpc/pmu/ebb/cpu_event_vs_ebb_test.c | 89 ++
> .../selftests/powerpc/pmu/ebb/cycles_test.c | 58 +
> .../powerpc/pmu/ebb/cycles_with_freeze_test.c | 117 ++
> tools/testing/selftests/powerpc/pmu/ebb/ebb.c | 727 +++++++++++++
> tools/testing/selftests/powerpc/pmu/ebb/ebb.h | 78 ++
> .../selftests/powerpc/pmu/ebb/ebb_handler.S | 365 +++++++
> .../selftests/powerpc/pmu/ebb/ebb_on_child_test.c | 86 ++
> .../powerpc/pmu/ebb/ebb_on_willing_child_test.c | 92 ++
> .../powerpc/pmu/ebb/ebb_vs_cpu_event_test.c | 86 ++
> .../powerpc/pmu/ebb/event_attributes_test.c | 131 +++
> .../powerpc/pmu/ebb/fixed_instruction_loop.S | 43 +
> .../selftests/powerpc/pmu/ebb/fork_cleanup_test.c | 79 ++
> .../powerpc/pmu/ebb/instruction_count_test.c | 164 +++
> .../powerpc/pmu/ebb/lost_exception_test.c | 100 ++
> .../selftests/powerpc/pmu/ebb/multi_counter_test.c | 91 ++
> .../powerpc/pmu/ebb/multi_ebb_procs_test.c | 109 ++
> .../selftests/powerpc/pmu/ebb/no_handler_test.c | 61 ++
> .../selftests/powerpc/pmu/ebb/pmae_handling_test.c | 106 ++
> .../powerpc/pmu/ebb/pmc56_overflow_test.c | 93 ++
> tools/testing/selftests/powerpc/pmu/ebb/reg.h | 49 +
> .../selftests/powerpc/pmu/ebb/reg_access_test.c | 39 +
> .../pmu/ebb/task_event_pinned_vs_ebb_test.c | 91 ++
> .../powerpc/pmu/ebb/task_event_vs_ebb_test.c | 83 ++
> tools/testing/selftests/powerpc/pmu/ebb/trace.c | 300 ++++++
> tools/testing/selftests/powerpc/pmu/ebb/trace.h | 41 +
> tools/testing/selftests/powerpc/pmu/event.c | 26 +
> tools/testing/selftests/powerpc/pmu/event.h | 4 +
> tools/testing/selftests/powerpc/pmu/lib.c | 252 +++++
> tools/testing/selftests/powerpc/pmu/lib.h | 41 +
> tools/testing/selftests/powerpc/pmu/loop.S | 73 +-
> tools/testing/selftests/powerpc/subunit.h | 5 +
> tools/testing/selftests/powerpc/tm/Makefile | 15 +
> .../testing/selftests/powerpc/tm/tm-resched-dscr.c | 90 ++
> tools/testing/selftests/powerpc/utils.h | 12 +
> 108 files changed, 4514 insertions(+), 4505 deletions(-)
> delete mode 100644 arch/powerpc/configs/chroma_defconfig
> delete mode 100644 arch/powerpc/include/asm/wsp.h
> delete mode 100644 arch/powerpc/kernel/cpu_setup_a2.S
> delete mode 100644 arch/powerpc/platforms/wsp/Kconfig
> delete mode 100644 arch/powerpc/platforms/wsp/Makefile
> delete mode 100644 arch/powerpc/platforms/wsp/chroma.c
> delete mode 100644 arch/powerpc/platforms/wsp/h8.c
> delete mode 100644 arch/powerpc/platforms/wsp/ics.c
> delete mode 100644 arch/powerpc/platforms/wsp/ics.h
> delete mode 100644 arch/powerpc/platforms/wsp/msi.c
> delete mode 100644 arch/powerpc/platforms/wsp/msi.h
> delete mode 100644 arch/powerpc/platforms/wsp/opb_pic.c
> delete mode 100644 arch/powerpc/platforms/wsp/psr2.c
> delete mode 100644 arch/powerpc/platforms/wsp/scom_smp.c
> delete mode 100644 arch/powerpc/platforms/wsp/scom_wsp.c
> delete mode 100644 arch/powerpc/platforms/wsp/setup.c
> delete mode 100644 arch/powerpc/platforms/wsp/smp.c
> delete mode 100644 arch/powerpc/platforms/wsp/wsp.c
> delete mode 100644 arch/powerpc/platforms/wsp/wsp.h
> delete mode 100644 arch/powerpc/platforms/wsp/wsp_pci.c
> delete mode 100644 arch/powerpc/platforms/wsp/wsp_pci.h
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/Makefile
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/back_to_back_ebbs_test.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/close_clears_pmcc_test.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/cpu_event_pinned_vs_ebb_test.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/cpu_event_vs_ebb_test.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/cycles_test.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/cycles_with_freeze_test.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/ebb.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/ebb.h
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/ebb_handler.S
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/ebb_on_child_test.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/ebb_on_willing_child_test.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/ebb_vs_cpu_event_test.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/event_attributes_test.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/fixed_instruction_loop.S
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/fork_cleanup_test.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/lost_exception_test.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/multi_counter_test.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/multi_ebb_procs_test.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/no_handler_test.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/pmae_handling_test.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/pmc56_overflow_test.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/reg.h
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/task_event_pinned_vs_ebb_test.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/task_event_vs_ebb_test.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/trace.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/ebb/trace.h
> create mode 100644 tools/testing/selftests/powerpc/pmu/lib.c
> create mode 100644 tools/testing/selftests/powerpc/pmu/lib.h
> create mode 100644 tools/testing/selftests/powerpc/tm/Makefile
> create mode 100644 tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
>
^ permalink raw reply
* RE: Kernel build issues after yesterdays merge by Linus
From: Christoph Lameter @ 2014-06-13 1:56 UTC (permalink / raw)
To: David Laight
Cc: Rusty Russell, linuxppc-dev@lists.ozlabs.org,
'Anton Blanchard'
In-Reply-To: <063D6719AE5E284EB5DD2968C1650D6D1725BABB@AcuExch.aculab.com>
Goobledieguy due to missing Mime header.
On Thu, 12 Jun 2014, David Laight wrote:
> RnJvbTogQW50b24gQmxhbmNoYXJkDQouLi4NCj4gZGlmZiAtLWdpdCBhL2FyY2gvcG93ZXJwYy9i
> b290L2luc3RhbGwuc2ggYi9hcmNoL3Bvd2VycGMvYm9vdC9pbnN0YWxsLnNoDQo+IGluZGV4IGI2
> YTI1NmIuLmUwOTZlNWEgMTAwNjQ0DQo+IC0tLSBhL2FyY2gvcG93ZXJwYy9ib290L2luc3RhbGwu
> c2gNCj4gKysrIGIvYXJjaC9wb3dlcnBjL2Jvb3QvaW5zdGFsbC5zaA0KPiBAQCAtMjMsOCArMjMs
> OCBAQCBzZXQgLWUNCj4gDQo+ICAjIFVzZXIgbWF5IGhhdmUgYSBjdXN0b20gaW5zdGFsbCBzY3Jp
> cHQNCj4gDQo+IC1pZiBbIC14IH4vYmluLyR7SU5TVEFMTEtFUk5FTH0gXTsgdGhlbiBleGVjIH4v
> YmluLyR7SU5TVEFMTEtFUk5FTH0gIiRAIjsgZmkNCj4gLWlmIFsgLXggL3NiaW4vJHtJTlNUQUxM
> S0VSTkVMfSBdOyB0aGVuIGV4ZWMgL3NiaW4vJHtJTlNUQUxMS0VSTkVMfSAiJEAiOyBmaQ0KPiAr
> aWYgWyAteCB+L2Jpbi8ke0lOU1RBTExLRVJORUx9IF07IHRoZW4gZXhlYyB+L2Jpbi8ke0lOU1RB
> TExLRVJORUx9ICQxICQyICQzICQ0OyBmaQ0KPiAraWYgWyAteCAvc2Jpbi8ke0lOU1RBTExLRVJO
> RUx9IF07IHRoZW4gZXhlYyAvc2Jpbi8ke0lOU1RBTExLRVJORUx9ICQxICQyICQzICQ0OyBmaQ0K
> DQpZb3UgcHJvYmFibHkgd2FudCB0byBlbmNsb3NlIHRoZSAkMSBpbiAiIGFzOg0KDQo+ICtpZiBb
> IC14IC9zYmluLyR7SU5TVEFMTEtFUk5FTH0gXTsgdGhlbiBleGVjIC9zYmluLyR7SU5TVEFMTEtF
> Uk5FTH0gIiQxIiAiJDIiICIkMyIgIiQ0IjsgZmkNCg0KCURhdmlkDQoNCg==
>
^ permalink raw reply
* Re: [alsa-devel] [RFC][PATCH v1] ASoC: fsl_ssi: Add DAI master mode support for SSI on i.MX series
From: Timur Tabi @ 2014-06-13 3:24 UTC (permalink / raw)
To: Nicolin Chen
Cc: Takashi Iwai, alsa-devel mailing list, Mark Brown,
linuxppc-dev@lists.ozlabs.org, Liam Girdwood
In-Reply-To: <1386845085-21682-1-git-send-email-Guangyu.Chen@freescale.com>
On Thu, Dec 12, 2013 at 4:44 AM, Nicolin Chen
<Guangyu.Chen@freescale.com> wrote:
>
> +static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
> + int clk_id, unsigned int freq, int dir)
> +{
> + struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
> + struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
> + int synchronous = ssi_private->cpu_dai_drv.symmetric_rates, ret;
> + u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
> + unsigned long flags, clkrate, baudrate, tmprate;
> + u64 sub, savesub = 100000;
> +
> + /* Don't apply it to any non-baudclk circumstance */
> + if (IS_ERR(ssi_private->baudclk))
> + return -EINVAL;
> +
> + /* It should be already enough to divide clock by setting pm alone */
> + psr = 0;
> + div2 = 0;
> +
> + factor = (div2 + 1) * (7 * psr + 1) * 2;
> +
> + for (i = 0; i < 255; i++) {
> + /* The bclk rate must be smaller than 1/5 sysclk rate */
> + if (factor * (i + 1) < 5)
> + continue;
> +
> + tmprate = freq * factor * (i + 2);
> + clkrate = clk_round_rate(ssi_private->baudclk, tmprate);
> +
> + do_div(clkrate, factor);
This do_div() call causes this warning on PowerPC:
CC sound/soc/fsl/fsl_ssi.o
sound/soc/fsl/fsl_ssi.c: In function 'fsl_ssi_set_bclk':
sound/soc/fsl/fsl_ssi.c:593:3: warning: comparison of distinct pointer
types lacks a cast
sound/soc/fsl/fsl_ssi.c:593:3: warning: right shift count >= width of type
sound/soc/fsl/fsl_ssi.c:593:3: warning: passing argument 1 of
'__div64_32' from incompatible pointer type
include/asm-generic/div64.h:35:17: note: expected 'uint64_t *' but
argument is of type 'long unsigned int *'
The comments in do_div() say that clkrate should be 64-bits. Changing
clkrate to a u64 does fix this problem, but I'm wondering if anyone
else has seen this. This code has been around for months.
^ permalink raw reply
* Re: [alsa-devel] [RFC][PATCH v1] ASoC: fsl_ssi: Add DAI master mode support for SSI on i.MX series
From: Nicolin Chen @ 2014-06-13 3:21 UTC (permalink / raw)
To: Timur Tabi
Cc: Takashi Iwai, alsa-devel mailing list, Mark Brown,
linuxppc-dev@lists.ozlabs.org, Liam Girdwood
In-Reply-To: <CAOZdJXWsxMq19-wNTKv6d45K4d79ASpMbSbofM+DMoTOKW2JJA@mail.gmail.com>
Sir,
On Thu, Jun 12, 2014 at 10:24:55PM -0500, Timur Tabi wrote:
> On Thu, Dec 12, 2013 at 4:44 AM, Nicolin Chen
> <Guangyu.Chen@freescale.com> wrote:
> >
> > +static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
> > + int clk_id, unsigned int freq, int dir)
> > +{
> > + struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
> > + struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
> > + int synchronous = ssi_private->cpu_dai_drv.symmetric_rates, ret;
> > + u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
> > + unsigned long flags, clkrate, baudrate, tmprate;
> > + u64 sub, savesub = 100000;
> > +
> > + /* Don't apply it to any non-baudclk circumstance */
> > + if (IS_ERR(ssi_private->baudclk))
> > + return -EINVAL;
> > +
> > + /* It should be already enough to divide clock by setting pm alone */
> > + psr = 0;
> > + div2 = 0;
> > +
> > + factor = (div2 + 1) * (7 * psr + 1) * 2;
> > +
> > + for (i = 0; i < 255; i++) {
> > + /* The bclk rate must be smaller than 1/5 sysclk rate */
> > + if (factor * (i + 1) < 5)
> > + continue;
> > +
> > + tmprate = freq * factor * (i + 2);
> > + clkrate = clk_round_rate(ssi_private->baudclk, tmprate);
> > +
> > + do_div(clkrate, factor);
>
> This do_div() call causes this warning on PowerPC:
>
> CC sound/soc/fsl/fsl_ssi.o
> sound/soc/fsl/fsl_ssi.c: In function 'fsl_ssi_set_bclk':
> sound/soc/fsl/fsl_ssi.c:593:3: warning: comparison of distinct pointer
> types lacks a cast
> sound/soc/fsl/fsl_ssi.c:593:3: warning: right shift count >= width of type
> sound/soc/fsl/fsl_ssi.c:593:3: warning: passing argument 1 of
> '__div64_32' from incompatible pointer type
> include/asm-generic/div64.h:35:17: note: expected 'uint64_t *' but
> argument is of type 'long unsigned int *'
>
> The comments in do_div() say that clkrate should be 64-bits. Changing
> clkrate to a u64 does fix this problem, but I'm wondering if anyone
> else has seen this. This code has been around for months.
It compiles well with my ARM cross compiler. I guess it might be related
to the compiler's version? But we should fix it anyway. Would you mind if
I submit a patch? Or you do it directly?
Thank you,
Nicolin
^ permalink raw reply
* Re: [alsa-devel] [RFC][PATCH v1] ASoC: fsl_ssi: Add DAI master mode support for SSI on i.MX series
From: Timur Tabi @ 2014-06-13 3:44 UTC (permalink / raw)
To: Nicolin Chen
Cc: alsa-devel mailing list, Takashi Iwai, Timur Tabi, Liam Girdwood,
Mark Brown, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20140613032119.GA15609@MrMyself>
On Thu, Jun 12, 2014 at 10:21 PM, Nicolin Chen
<Guangyu.Chen@freescale.com> wrote:
> It compiles well with my ARM cross compiler. I guess it might be related
> to the compiler's version? But we should fix it anyway. Would you mind if
> I submit a patch? Or you do it directly?
I just submitted a patch, but I can't test the code since I don't have
any boards that configure the SSI into master mode, so this function
is never called.
^ permalink raw reply
* Re: [alsa-devel] [RFC][PATCH v1] ASoC: fsl_ssi: Add DAI master mode support for SSI on i.MX series
From: Nicolin Chen @ 2014-06-13 3:50 UTC (permalink / raw)
To: Timur Tabi
Cc: Takashi Iwai, alsa-devel mailing list, Mark Brown,
linuxppc-dev@lists.ozlabs.org, Liam Girdwood
In-Reply-To: <CAOZdJXUUz2bufcYmt9U-x0bic6XU68VHLOiPPsHoEdSZmnisZw@mail.gmail.com>
On Thu, Jun 12, 2014 at 10:44:48PM -0500, Timur Tabi wrote:
> On Thu, Jun 12, 2014 at 10:21 PM, Nicolin Chen
> <Guangyu.Chen@freescale.com> wrote:
>
> > It compiles well with my ARM cross compiler. I guess it might be related
> > to the compiler's version? But we should fix it anyway. Would you mind if
> > I submit a patch? Or you do it directly?
>
> I just submitted a patch, but I can't test the code since I don't have
> any boards that configure the SSI into master mode, so this function
> is never called.
I just tested it with i.MX platform. It still works.
Thank you,
Nicolin
^ permalink raw reply
* Re: Kernel build issues after yesterdays merge by Linus
From: Tony Breeds @ 2014-06-13 5:15 UTC (permalink / raw)
To: Anton Blanchard; +Cc: Rusty Russell, linuxppc-dev, Christoph Lameter
In-Reply-To: <20140612220912.3447677f@kryten>
[-- Attachment #1: Type: text/plain, Size: 1704 bytes --]
On Thu, Jun 12, 2014 at 10:09:12PM +1000, Anton Blanchard wrote:
> The TOC symbol export is special and I think we might need to get our
> script to ignore it.
Try this (untested) patch. If it's good I'll send it to Ben.
diff --git a/arch/powerpc/relocs_check.pl b/arch/powerpc/relocs_check.pl
index 3f46e8b..34e3f25 100755
--- a/arch/powerpc/relocs_check.pl
+++ b/arch/powerpc/relocs_check.pl
@@ -45,6 +45,9 @@ while (<FD>) {
/\bR_PPC_ADDR16_HA\b/ or /\bR_PPC_RELATIVE\b/ or
/\bR_PPC_NONE\b/);
+ # The TOC is "special" so let's ignore it.
+ next if (/__crc_TOC\./);
+
# If we see this type of relocation it's an idication that
# we /may/ be using an old version of binutils.
if (/R_PPC64_UADDR64/) {
<snip>
> Shows how much we use make install :) Below is a quick hack to get you going
> but we should look at either fixing the Ubuntu installkernel to handle
> extra optional args, or stop passing them from the ppc64 kernel
> install.sh script.
It seems like passign the zImage files is probably wrong. How about:
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index ccc25ed..146d898 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -390,7 +390,7 @@ $(obj)/zImage.initrd: $(addprefix $(obj)/, $(initrd-y))
@rm -f $@; ln $< $@
install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y))
- sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $^
+ sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)"
# anything not in $(targets)
clean-files += $(image-) $(initrd-) cuImage.* dtbImage.* treeImage.* \
[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply related
* [PATCH] KVM: PPC: BOOK3S: HV: Use base page size when comparing against slb value
From: Aneesh Kumar K.V @ 2014-06-13 7:23 UTC (permalink / raw)
To: agraf, benh, paulus; +Cc: linuxppc-dev, kvm, kvm-ppc, Aneesh Kumar K.V
With guest supporting Multiple page size per segment (MPSS),
hpte_page_size returns actual page size used. Add a new function to
return base page size and use that to compare against the the page size
calculated from SLB
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/kvm_book3s_64.h | 19 +++++++++++++++++--
arch/powerpc/kvm/book3s_64_mmu_hv.c | 2 +-
arch/powerpc/kvm/book3s_hv_rm_mmu.c | 2 +-
3 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
index 34422be566ce..3d0f3fb9c6b6 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
@@ -202,8 +202,10 @@ static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
return rb;
}
-static inline unsigned long hpte_page_size(unsigned long h, unsigned long l)
+static inline unsigned long __hpte_page_size(unsigned long h, unsigned long l,
+ bool is_base_size)
{
+
int size, a_psize;
/* Look at the 8 bit LP value */
unsigned int lp = (l >> LP_SHIFT) & ((1 << LP_BITS) - 1);
@@ -218,14 +220,27 @@ static inline unsigned long hpte_page_size(unsigned long h, unsigned long l)
continue;
a_psize = __hpte_actual_psize(lp, size);
- if (a_psize != -1)
+ if (a_psize != -1) {
+ if (is_base_size)
+ return 1ul << mmu_psize_defs[size].shift;
return 1ul << mmu_psize_defs[a_psize].shift;
+ }
}
}
return 0;
}
+static inline unsigned long hpte_page_size(unsigned long h, unsigned long l)
+{
+ return __hpte_page_size(h, l, 0);
+}
+
+static inline unsigned long hpte_base_page_size(unsigned long h, unsigned long l)
+{
+ return __hpte_page_size(h, l, 1);
+}
+
static inline unsigned long hpte_rpn(unsigned long ptel, unsigned long psize)
{
return ((ptel & HPTE_R_RPN) & ~(psize - 1)) >> PAGE_SHIFT;
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index f53cf2eae36a..7ff45ed27c65 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -1567,7 +1567,7 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf,
goto out;
}
if (!rma_setup && is_vrma_hpte(v)) {
- unsigned long psize = hpte_page_size(v, r);
+ unsigned long psize = hpte_base_page_size(v, r);
unsigned long senc = slb_pgsize_encoding(psize);
unsigned long lpcr;
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index 87624ab5ba82..c6aca75b8376 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -839,7 +839,7 @@ long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v,
* to check against the actual page size.
*/
if ((v & valid) && (v & mask) == val &&
- hpte_page_size(v, r) == (1ul << pshift))
+ hpte_base_page_size(v, r) == (1ul << pshift))
/* Return with the HPTE still locked */
return (hash << 3) + (i >> 1);
--
1.9.1
^ permalink raw reply related
* Re: [alsa-devel] [RFC][PATCH v1] ASoC: fsl_ssi: Add DAI master mode support for SSI on i.MX series
From: Takashi Iwai @ 2014-06-13 9:00 UTC (permalink / raw)
To: Timur Tabi
Cc: alsa-devel mailing list, Mark Brown,
linuxppc-dev@lists.ozlabs.org, Liam Girdwood, Nicolin Chen
In-Reply-To: <CAOZdJXWsxMq19-wNTKv6d45K4d79ASpMbSbofM+DMoTOKW2JJA@mail.gmail.com>
At Thu, 12 Jun 2014 22:24:55 -0500,
Timur Tabi wrote:
>
> On Thu, Dec 12, 2013 at 4:44 AM, Nicolin Chen
> <Guangyu.Chen@freescale.com> wrote:
> >
> > +static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
> > + int clk_id, unsigned int freq, int dir)
> > +{
> > + struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
> > + struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
> > + int synchronous = ssi_private->cpu_dai_drv.symmetric_rates, ret;
> > + u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
> > + unsigned long flags, clkrate, baudrate, tmprate;
> > + u64 sub, savesub = 100000;
> > +
> > + /* Don't apply it to any non-baudclk circumstance */
> > + if (IS_ERR(ssi_private->baudclk))
> > + return -EINVAL;
> > +
> > + /* It should be already enough to divide clock by setting pm alone */
> > + psr = 0;
> > + div2 = 0;
> > +
> > + factor = (div2 + 1) * (7 * psr + 1) * 2;
> > +
> > + for (i = 0; i < 255; i++) {
> > + /* The bclk rate must be smaller than 1/5 sysclk rate */
> > + if (factor * (i + 1) < 5)
> > + continue;
> > +
> > + tmprate = freq * factor * (i + 2);
> > + clkrate = clk_round_rate(ssi_private->baudclk, tmprate);
> > +
> > + do_div(clkrate, factor);
>
> This do_div() call causes this warning on PowerPC:
>
> CC sound/soc/fsl/fsl_ssi.o
> sound/soc/fsl/fsl_ssi.c: In function 'fsl_ssi_set_bclk':
> sound/soc/fsl/fsl_ssi.c:593:3: warning: comparison of distinct pointer
> types lacks a cast
> sound/soc/fsl/fsl_ssi.c:593:3: warning: right shift count >= width of type
> sound/soc/fsl/fsl_ssi.c:593:3: warning: passing argument 1 of
> '__div64_32' from incompatible pointer type
> include/asm-generic/div64.h:35:17: note: expected 'uint64_t *' but
> argument is of type 'long unsigned int *'
>
> The comments in do_div() say that clkrate should be 64-bits. Changing
> clkrate to a u64 does fix this problem, but I'm wondering if anyone
> else has seen this. This code has been around for months.
Using do_div() for unsigned long makes no sense.
And, you *must* pass uint64_t there as an argument, since it's no
inline function and there is no implicit conversion in the generic
code.
In short, use the normal division operator instead:
clkrate /= factor;
Takashi
^ permalink raw reply
* Re: kmemleak: Unable to handle kernel paging request
From: Catalin Marinas @ 2014-06-13 8:56 UTC (permalink / raw)
To: Denis Kirjanov
Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org, Paul Mackerras,
Naoya Horiguchi, linuxppc-dev
In-Reply-To: <CAOJe8K3zN+fFWumKaGx3Tmv5JRZu10_FZ6R3Tjjc+nc-KVB0hg@mail.gmail.com>
On Fri, Jun 13, 2014 at 08:12:08AM +0100, Denis Kirjanov wrote:
> On 6/12/14, Catalin Marinas <catalin.marinas@arm.com> wrote:
> > On Thu, Jun 12, 2014 at 01:00:57PM +0100, Denis Kirjanov wrote:
> >> On 6/12/14, Denis Kirjanov <kda@linux-powerpc.org> wrote:
> >> > On 6/12/14, Catalin Marinas <catalin.marinas@arm.com> wrote:
> >> >> On 11 Jun 2014, at 21:04, Denis Kirjanov <kda@linux-powerpc.org>
> >> >> wrote:
> >> >>> On 6/11/14, Catalin Marinas <catalin.marinas@arm.com> wrote:
> >> >>>> On Wed, Jun 11, 2014 at 04:13:07PM +0400, Denis Kirjanov wrote:
> >> >>>>> I got a trace while running 3.15.0-08556-gdfb9454:
> >> >>>>>
> >> >>>>> [ 104.534026] Unable to handle kernel paging request for data at
> >> >>>>> address 0xc00000007f000000
> >> >>>>
> >> >>>> Were there any kmemleak messages prior to this, like "kmemleak
> >> >>>> disabled"? There could be a race when kmemleak is disabled because
> >> >>>> of
> >> >>>> some fatal (for kmemleak) error while the scanning is taking place
> >> >>>> (which needs some more thinking to fix properly).
> >> >>>
> >> >>> No. I checked for the similar problem and didn't find anything
> >> >>> relevant.
> >> >>> I'll try to bisect it.
> >> >>
> >> >> Does this happen soon after boot? I guess it’s the first scan
> >> >> (scheduled at around 1min after boot). Something seems to be telling
> >> >> kmemleak that there is a valid memory block at 0xc00000007f000000.
> >> >
> >> > Yeah, it happens after a while with a booted system so that's the
> >> > first kmemleak scan.
> >>
> >> I've bisected to this commit: d4c54919ed86302094c0ca7d48a8cbd4ee753e92
> >> "mm: add !pte_present() check on existing hugetlb_entry callbacks".
> >> Reverting the commit fixes the issue
> >
> > I can't figure how this causes the problem but I have more questions. Is
> > 0xc00000007f000000 address always the same in all crashes? If yes, you
> > could comment out start_scan_thread() in kmemleak_late_init() to avoid
> > the scanning thread starting. Once booted, you can run:
> >
> > echo dump=0xc00000007f000000 > /sys/kernel/debug/kmemleak
> >
> > and check the dmesg for what kmemleak knows about that address, when it
> > was allocated and whether it should be mapped or not.
>
> The address is always the same.
>
> [ 179.466239] kmemleak: Object 0xc00000007f000000 (size 16777216):
> [ 179.466503] kmemleak: comm "swapper/0", pid 0, jiffies 4294892300
> [ 179.466508] kmemleak: min_count = 0
> [ 179.466512] kmemleak: count = 0
> [ 179.466517] kmemleak: flags = 0x1
> [ 179.466522] kmemleak: checksum = 0
> [ 179.466526] kmemleak: backtrace:
> [ 179.466531] [<c000000000afc3dc>] .memblock_alloc_range_nid+0x68/0x88
> [ 179.466544] [<c000000000afc444>] .memblock_alloc_base+0x20/0x58
> [ 179.466553] [<c000000000ae96cc>] .alloc_dart_table+0x5c/0xb0
> [ 179.466561] [<c000000000aea300>] .pmac_probe+0x38/0xa0
> [ 179.466569] [<000000000002166c>] 0x2166c
> [ 179.466579] [<0000000000ae0e68>] 0xae0e68
> [ 179.466587] [<0000000000009bc4>] 0x9bc4
OK, so that's the DART table allocated via alloc_dart_table(). Is
dart_tablebase removed from the kernel linear mapping after allocation?
If that's the case, we need to tell kmemleak to ignore this block (see
patch below, untested). But I still can't explain how commit
d4c54919ed863020 causes this issue.
(also cc'ing the powerpc list and maintainers)
---------------8<--------------------------
>From 09a7f1c97166c7bdca7ca4e8a4ff2774f3706ea3 Mon Sep 17 00:00:00 2001
From: Catalin Marinas <catalin.marinas@arm.com>
Date: Fri, 13 Jun 2014 09:44:21 +0100
Subject: [PATCH] powerpc/kmemleak: Do not scan the DART table
The DART table allocation is registered to kmemleak via the
memblock_alloc_base() call. However, the DART table is later unmapped
and dart_tablebase VA no longer accessible. This patch tells kmemleak
not to scan this block and avoid an unhandled paging request.
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
---
arch/powerpc/sysdev/dart_iommu.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 62c47bb76517..9e5353ff6d1b 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -476,6 +476,11 @@ void __init alloc_dart_table(void)
*/
dart_tablebase = (unsigned long)
__va(memblock_alloc_base(1UL<<24, 1UL<<24, 0x80000000L));
+ /*
+ * The DART space is later unmapped from the kernel linear mapping and
+ * accessing dart_tablebase during kmemleak scanning will fault.
+ */
+ kmemleak_no_scan((void *)dart_tablebase);
printk(KERN_INFO "DART table allocated at: %lx\n", dart_tablebase);
}
^ permalink raw reply related
* Re: [alsa-devel] [RFC][PATCH v1] ASoC: fsl_ssi: Add DAI master mode support for SSI on i.MX series
From: Nicolin Chen @ 2014-06-13 8:56 UTC (permalink / raw)
To: Takashi Iwai
Cc: alsa-devel mailing list, Mark Brown,
linuxppc-dev@lists.ozlabs.org, Timur Tabi, Liam Girdwood
In-Reply-To: <s5hioo5gp66.wl%tiwai@suse.de>
On Fri, Jun 13, 2014 at 11:00:01AM +0200, Takashi Iwai wrote:
> At Thu, 12 Jun 2014 22:24:55 -0500,
> Timur Tabi wrote:
> >
> > On Thu, Dec 12, 2013 at 4:44 AM, Nicolin Chen
> > <Guangyu.Chen@freescale.com> wrote:
> > >
> > > +static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
> > > + int clk_id, unsigned int freq, int dir)
> > > +{
> > > + struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
> > > + struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
> > > + int synchronous = ssi_private->cpu_dai_drv.symmetric_rates, ret;
> > > + u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
> > > + unsigned long flags, clkrate, baudrate, tmprate;
> > > + u64 sub, savesub = 100000;
> > > +
> > > + /* Don't apply it to any non-baudclk circumstance */
> > > + if (IS_ERR(ssi_private->baudclk))
> > > + return -EINVAL;
> > > +
> > > + /* It should be already enough to divide clock by setting pm alone */
> > > + psr = 0;
> > > + div2 = 0;
> > > +
> > > + factor = (div2 + 1) * (7 * psr + 1) * 2;
> > > +
> > > + for (i = 0; i < 255; i++) {
> > > + /* The bclk rate must be smaller than 1/5 sysclk rate */
> > > + if (factor * (i + 1) < 5)
> > > + continue;
> > > +
> > > + tmprate = freq * factor * (i + 2);
> > > + clkrate = clk_round_rate(ssi_private->baudclk, tmprate);
> > > +
> > > + do_div(clkrate, factor);
> >
> > This do_div() call causes this warning on PowerPC:
> >
> > CC sound/soc/fsl/fsl_ssi.o
> > sound/soc/fsl/fsl_ssi.c: In function 'fsl_ssi_set_bclk':
> > sound/soc/fsl/fsl_ssi.c:593:3: warning: comparison of distinct pointer
> > types lacks a cast
> > sound/soc/fsl/fsl_ssi.c:593:3: warning: right shift count >= width of type
> > sound/soc/fsl/fsl_ssi.c:593:3: warning: passing argument 1 of
> > '__div64_32' from incompatible pointer type
> > include/asm-generic/div64.h:35:17: note: expected 'uint64_t *' but
> > argument is of type 'long unsigned int *'
> >
> > The comments in do_div() say that clkrate should be 64-bits. Changing
> > clkrate to a u64 does fix this problem, but I'm wondering if anyone
> > else has seen this. This code has been around for months.
>
> Using do_div() for unsigned long makes no sense.
> And, you *must* pass uint64_t there as an argument, since it's no
> inline function and there is no implicit conversion in the generic
> code.
>
> In short, use the normal division operator instead:
> clkrate /= factor;
Yes. I forgot why I used do_div() for clkrate at the first place
but it's definitely a mistake here.
Sorry,
Nicolin
>
>
> Takashi
^ permalink raw reply
* Re: [PATCH] KVM: PPC: BOOK3S: HV: Use base page size when comparing against slb value
From: Alexander Graf @ 2014-06-13 10:03 UTC (permalink / raw)
To: Aneesh Kumar K.V, benh, paulus; +Cc: linuxppc-dev, kvm, kvm-ppc
In-Reply-To: <1402644190-15604-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com>
On 13.06.14 09:23, Aneesh Kumar K.V wrote:
> With guest supporting Multiple page size per segment (MPSS),
> hpte_page_size returns actual page size used. Add a new function to
> return base page size and use that to compare against the the page size
> calculated from SLB
Why? What does this fix? Is this a bug fix, an enhancement? Don't
describe only what you do, but also why you do it.
Alex
>
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
> ---
> arch/powerpc/include/asm/kvm_book3s_64.h | 19 +++++++++++++++++--
> arch/powerpc/kvm/book3s_64_mmu_hv.c | 2 +-
> arch/powerpc/kvm/book3s_hv_rm_mmu.c | 2 +-
> 3 files changed, 19 insertions(+), 4 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
> index 34422be566ce..3d0f3fb9c6b6 100644
> --- a/arch/powerpc/include/asm/kvm_book3s_64.h
> +++ b/arch/powerpc/include/asm/kvm_book3s_64.h
> @@ -202,8 +202,10 @@ static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
> return rb;
> }
>
> -static inline unsigned long hpte_page_size(unsigned long h, unsigned long l)
> +static inline unsigned long __hpte_page_size(unsigned long h, unsigned long l,
> + bool is_base_size)
> {
> +
> int size, a_psize;
> /* Look at the 8 bit LP value */
> unsigned int lp = (l >> LP_SHIFT) & ((1 << LP_BITS) - 1);
> @@ -218,14 +220,27 @@ static inline unsigned long hpte_page_size(unsigned long h, unsigned long l)
> continue;
>
> a_psize = __hpte_actual_psize(lp, size);
> - if (a_psize != -1)
> + if (a_psize != -1) {
> + if (is_base_size)
> + return 1ul << mmu_psize_defs[size].shift;
> return 1ul << mmu_psize_defs[a_psize].shift;
> + }
> }
>
> }
> return 0;
> }
>
> +static inline unsigned long hpte_page_size(unsigned long h, unsigned long l)
> +{
> + return __hpte_page_size(h, l, 0);
> +}
> +
> +static inline unsigned long hpte_base_page_size(unsigned long h, unsigned long l)
> +{
> + return __hpte_page_size(h, l, 1);
> +}
> +
> static inline unsigned long hpte_rpn(unsigned long ptel, unsigned long psize)
> {
> return ((ptel & HPTE_R_RPN) & ~(psize - 1)) >> PAGE_SHIFT;
> diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
> index f53cf2eae36a..7ff45ed27c65 100644
> --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
> +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
> @@ -1567,7 +1567,7 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf,
> goto out;
> }
> if (!rma_setup && is_vrma_hpte(v)) {
> - unsigned long psize = hpte_page_size(v, r);
> + unsigned long psize = hpte_base_page_size(v, r);
> unsigned long senc = slb_pgsize_encoding(psize);
> unsigned long lpcr;
>
> diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
> index 87624ab5ba82..c6aca75b8376 100644
> --- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
> +++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
> @@ -839,7 +839,7 @@ long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v,
> * to check against the actual page size.
> */
> if ((v & valid) && (v & mask) == val &&
> - hpte_page_size(v, r) == (1ul << pshift))
> + hpte_base_page_size(v, r) == (1ul << pshift))
> /* Return with the HPTE still locked */
> return (hash << 3) + (i >> 1);
>
^ permalink raw reply
* [RFC][PATCH 0/2] Add ASRC Peripheral to Peripheral driver
From: Nicolin Chen @ 2014-06-13 10:07 UTC (permalink / raw)
To: broonie, vinod.koul, s.hauer
Cc: mark.rutland, devicetree, alsa-devel, b42378, timur, pawel.moll,
ijc+devicetree, tiwai, linux-kernel, b02247, rdunlap, linux-doc,
lgirdwood, b38343, perex, dmaengine, robh+dt, galak, grant.likely,
dan.j.williams, linuxppc-dev
This series of patches have a direct dependency between them. So we might
need to push them into one branch. And sorry for this :(
Patch-1 adds device to device support in SDMA driver along with a secondary
request in struct imx_dma_data which's requred in the Patch-2 ASRC driver.
Nicolin Chen (2):
dma: imx-sdma: Add device to device support
ASoC: fsl_asrc: Add ASRC ASoC CPU DAI and platform drivers
.../devicetree/bindings/sound/fsl,asrc.txt | 62 ++
drivers/dma/imx-sdma.c | 40 +-
include/linux/platform_data/dma-imx.h | 1 +
sound/soc/fsl/Kconfig | 9 +
sound/soc/fsl/Makefile | 2 +
sound/soc/fsl/fsl_asrc.c | 1031 ++++++++++++++++++++
sound/soc/fsl/fsl_asrc.h | 431 ++++++++
sound/soc/fsl/fsl_asrc_dma.c | 385 ++++++++
8 files changed, 1956 insertions(+), 5 deletions(-)
create mode 100644 Documentation/devicetree/bindings/sound/fsl,asrc.txt
create mode 100644 sound/soc/fsl/fsl_asrc.c
create mode 100644 sound/soc/fsl/fsl_asrc.h
create mode 100644 sound/soc/fsl/fsl_asrc_dma.c
--
1.8.4
^ permalink raw reply
* [RFC][PATCH 1/2] dma: imx-sdma: Add device to device support
From: Nicolin Chen @ 2014-06-13 10:07 UTC (permalink / raw)
To: broonie, vinod.koul, s.hauer
Cc: mark.rutland, devicetree, alsa-devel, b42378, timur, pawel.moll,
ijc+devicetree, tiwai, linux-kernel, b02247, rdunlap, linux-doc,
lgirdwood, b38343, perex, dmaengine, robh+dt, galak, grant.likely,
dan.j.williams, linuxppc-dev
In-Reply-To: <cover.1402653667.git.nicoleotsuka@gmail.com>
This patch adds DEV_TO_DEV support for i.MX SDMA driver to support data
tranfer between two peripheral FIFOs. The per_2_per script requires two
peripheral addresses and two DMA requests. So this patch also adds them
into private structure.
Signed-off-by: Nicolin Chen <nicoleotsuka@gmail.com>
---
drivers/dma/imx-sdma.c | 40 ++++++++++++++++++++++++++++++-----
include/linux/platform_data/dma-imx.h | 1 +
2 files changed, 36 insertions(+), 5 deletions(-)
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 85561dc..5af1a69 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -258,8 +258,9 @@ struct sdma_channel {
struct sdma_buffer_descriptor *bd;
dma_addr_t bd_phys;
unsigned int pc_from_device, pc_to_device;
+ unsigned int device_to_device;
unsigned long flags;
- dma_addr_t per_address;
+ dma_addr_t per_address, per_address2;
unsigned long event_mask[2];
unsigned long watermark_level;
u32 shp_addr, per_addr;
@@ -696,6 +697,7 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
sdmac->pc_from_device = 0;
sdmac->pc_to_device = 0;
+ sdmac->device_to_device = 0;
switch (peripheral_type) {
case IMX_DMATYPE_MEMORY:
@@ -770,6 +772,7 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
sdmac->pc_from_device = per_2_emi;
sdmac->pc_to_device = emi_2_per;
+ sdmac->device_to_device = per_2_per;
}
static int sdma_load_context(struct sdma_channel *sdmac)
@@ -782,11 +785,12 @@ static int sdma_load_context(struct sdma_channel *sdmac)
int ret;
unsigned long flags;
- if (sdmac->direction == DMA_DEV_TO_MEM) {
+ if (sdmac->direction == DMA_DEV_TO_MEM)
load_address = sdmac->pc_from_device;
- } else {
+ else if (sdmac->direction == DMA_DEV_TO_DEV)
+ load_address = sdmac->device_to_device;
+ else
load_address = sdmac->pc_to_device;
- }
if (load_address < 0)
return load_address;
@@ -850,6 +854,12 @@ static int sdma_config_channel(struct sdma_channel *sdmac)
sdma_event_enable(sdmac, sdmac->event_id0);
}
+ if (sdmac->event_id1) {
+ if (sdmac->event_id1 >= sdmac->sdma->drvdata->num_events)
+ return -EINVAL;
+ sdma_event_enable(sdmac, sdmac->event_id1);
+ }
+
switch (sdmac->peripheral_type) {
case IMX_DMATYPE_DSP:
sdma_config_ownership(sdmac, false, true, true);
@@ -880,7 +890,12 @@ static int sdma_config_channel(struct sdma_channel *sdmac)
/* Watermark Level */
sdmac->watermark_level |= sdmac->watermark_level;
/* Address */
- sdmac->shp_addr = sdmac->per_address;
+ if (sdmac->direction == DMA_DEV_TO_DEV) {
+ sdmac->shp_addr = sdmac->per_address2;
+ sdmac->per_addr = sdmac->per_address;
+ } else {
+ sdmac->shp_addr = sdmac->per_address;
+ }
} else {
sdmac->watermark_level = 0; /* FIXME: M3_BASE_ADDRESS */
}
@@ -974,6 +989,7 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan)
sdmac->peripheral_type = data->peripheral_type;
sdmac->event_id0 = data->dma_request;
+ sdmac->event_id1 = data->dma_request2;
clk_enable(sdmac->sdma->clk_ipg);
clk_enable(sdmac->sdma->clk_ahb);
@@ -1213,6 +1229,19 @@ static int sdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
sdmac->watermark_level = dmaengine_cfg->src_maxburst *
dmaengine_cfg->src_addr_width;
sdmac->word_size = dmaengine_cfg->src_addr_width;
+ } else if (dmaengine_cfg->direction == DMA_DEV_TO_DEV) {
+ sdmac->per_address = dmaengine_cfg->src_addr;
+ sdmac->per_address2 = dmaengine_cfg->dst_addr;
+ /*
+ * For per_2_per sciprt, register r7 requires two
+ * watermark levels: the lower placed at bits [0-7]
+ * and the higher one placed at bits [16-23].
+ */
+ sdmac->watermark_level =
+ dmaengine_cfg->src_maxburst & 0xff;
+ sdmac->watermark_level |=
+ (dmaengine_cfg->dst_maxburst & 0xff) << 16;
+ sdmac->word_size = dmaengine_cfg->dst_addr_width;
} else {
sdmac->per_address = dmaengine_cfg->dst_addr;
sdmac->watermark_level = dmaengine_cfg->dst_maxburst *
@@ -1433,6 +1462,7 @@ static struct dma_chan *sdma_xlate(struct of_phandle_args *dma_spec,
data.dma_request = dma_spec->args[0];
data.peripheral_type = dma_spec->args[1];
data.priority = dma_spec->args[2];
+ data.dma_request2 = 0;
return dma_request_channel(mask, sdma_filter_fn, &data);
}
diff --git a/include/linux/platform_data/dma-imx.h b/include/linux/platform_data/dma-imx.h
index 7aa0e89..6a1357d 100644
--- a/include/linux/platform_data/dma-imx.h
+++ b/include/linux/platform_data/dma-imx.h
@@ -51,6 +51,7 @@ enum imx_dma_prio {
struct imx_dma_data {
int dma_request; /* DMA request line */
+ int dma_request2; /* secondary DMA request line */
enum sdma_peripheral_type peripheral_type;
int priority;
};
--
1.8.4
^ permalink raw reply related
* [RFC][PATCH 2/2] ASoC: fsl_asrc: Add ASRC ASoC CPU DAI and platform drivers
From: Nicolin Chen @ 2014-06-13 10:07 UTC (permalink / raw)
To: broonie, vinod.koul, s.hauer
Cc: mark.rutland, devicetree, alsa-devel, b42378, timur, pawel.moll,
ijc+devicetree, tiwai, linux-kernel, b02247, rdunlap, linux-doc,
lgirdwood, b38343, perex, dmaengine, robh+dt, galak, grant.likely,
dan.j.williams, linuxppc-dev
In-Reply-To: <cover.1402653667.git.nicoleotsuka@gmail.com>
The Asynchronous Sample Rate Converter (ASRC) converts the sampling rate of a
signal associated with an input clock into a signal associated with a different
output clock. The driver currently works as a Front End of DPCM with other Back
Ends DAI links such as ESAI<->CS42888 and SSI<->WM8962 and SAI. It converts the
original sample rate to a common rate supported by Back Ends for playback while
converts the common rate of Back Ends to a desired rate. It has three pairs to
support three different substreams within totally 10 channels.
Signed-off-by: Nicolin Chen <nicoleotsuka@gmail.com>
---
------!RFC!-----
A disscusstion should be made regarding asrc-rate and asrc-width bindings.
It's currently put in ASRC which makes these two parameters fixed for all
Back Ends. It may be better to put them into sound nodes (machine driver's).
However, I can't find a good approach to pass them back into ASRC driver.
------!RFC!-----
.../devicetree/bindings/sound/fsl,asrc.txt | 62 ++
sound/soc/fsl/Kconfig | 9 +
sound/soc/fsl/Makefile | 2 +
sound/soc/fsl/fsl_asrc.c | 1031 ++++++++++++++++++++
sound/soc/fsl/fsl_asrc.h | 431 ++++++++
sound/soc/fsl/fsl_asrc_dma.c | 385 ++++++++
6 files changed, 1920 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/fsl,asrc.txt
create mode 100644 sound/soc/fsl/fsl_asrc.c
create mode 100644 sound/soc/fsl/fsl_asrc.h
create mode 100644 sound/soc/fsl/fsl_asrc_dma.c
diff --git a/Documentation/devicetree/bindings/sound/fsl,asrc.txt b/Documentation/devicetree/bindings/sound/fsl,asrc.txt
new file mode 100644
index 0000000..637028c
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/fsl,asrc.txt
@@ -0,0 +1,62 @@
+Freescale Asynchronous Sample Rate Converter (ASRC) Controller
+
+The Asynchronous Sample Rate Converter (ASRC) converts the sampling rate of a
+signal associated with an input clock into a signal associated with a different
+output clock. The driver currently works as a Front End of DPCM with other Back
+Ends Audio controller such as ESAI, SSI and SAI. It has three pairs to support
+three substreams within totally 10 channels.
+
+Required properties:
+
+ - compatible : Compatible list, must contain "fsl,imx35-asrc" or
+ "fsl,imx53-asrc".
+
+ - reg : Offset and length of the register set for the device.
+
+ - interrupts : Contains the spdif interrupt.
+
+ - dmas : Generic dma devicetree binding as described in
+ Documentation/devicetree/bindings/dma/dma.txt.
+
+ - dma-names : Six dmas have to be defined: "rxa", "rxb", "rxc", "txa", "txb",
+ and "txc".
+
+ - clocks : Contains an entry for each entry in clock-names.
+
+ - clock-names : Includes the following entries:
+ "mem" Peripheral access clock to access registers.
+ "ipg" Peripheral clock to driver module.
+ "asrck_<0-f>" Clock sources for input and output clock.
+
+ - big-endian : If this property is absent, the native endian mode will
+ be in use as default, or the big endian mode will be in use
+ for all the device registers.
+
+ - fsl,asrc-rate : Defines a mutual sample rate used by Back End DAI link.
+
+ - fsl,asrc-width : Defines a mutual sample width used by Back End DAI link.
+
+Example:
+
+asrc: asrc@02034000 {
+ compatible = "fsl,imx53-asrc";
+ reg = <0x02034000 0x4000>;
+ interrupts = <0 50 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks 107>, <&clks 107>, <&clks 0>,
+ <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+ <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+ <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+ <&clks 107>, <&clks 0>, <&clks 0>;
+ clock-names = "mem", "ipg", "asrck0",
+ "asrck_1", "asrck_2", "asrck_3", "asrck_4",
+ "asrck_5", "asrck_6", "asrck_7", "asrck_8",
+ "asrck_9", "asrck_a", "asrck_b", "asrck_c",
+ "asrck_d", "asrck_e", "asrck_f";
+ dmas = <&sdma 17 23 1>, <&sdma 18 23 1>, <&sdma 19 23 1>,
+ <&sdma 20 23 1>, <&sdma 21 23 1>, <&sdma 22 23 1>;
+ dma-names = "rxa", "rxb", "rxc",
+ "txa", "txb", "txc";
+ fsl,asrc-rate = <48000>;
+ fsl,asrc-width = <16>;
+ status = "okay";
+};
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index aeccdd4..b269714 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -2,6 +2,15 @@ menu "SoC Audio for Freescale CPUs"
comment "Common SoC Audio options for Freescale CPUs:"
+config SND_SOC_FSL_ASRC
+ tristate "Asynchronous Sample Rate Converter (ASRC) module support"
+ select REGMAP_MMIO
+ help
+ Say Y if you want to add Asynchronous Sample Rate Converter (ASRC)
+ support for the Freescale CPUs.
+ This option is only useful for out-of-tree drivers since
+ in-tree drivers select it automatically.
+
config SND_SOC_FSL_SAI
tristate "Synchronous Audio Interface (SAI) module support"
select REGMAP_MMIO
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index ce49570..ff7ee2c 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -11,6 +11,7 @@ snd-soc-p1022-rdk-objs := p1022_rdk.o
obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o
# Freescale SSI/DMA/SAI/SPDIF Support
+snd-soc-fsl-asrc-objs := fsl_asrc.o fsl_asrc_dma.o
snd-soc-fsl-sai-objs := fsl_sai.o
snd-soc-fsl-ssi-y := fsl_ssi.o
snd-soc-fsl-ssi-$(CONFIG_DEBUG_FS) += fsl_ssi_dbg.o
@@ -18,6 +19,7 @@ snd-soc-fsl-spdif-objs := fsl_spdif.o
snd-soc-fsl-esai-objs := fsl_esai.o
snd-soc-fsl-utils-objs := fsl_utils.o
snd-soc-fsl-dma-objs := fsl_dma.o
+obj-$(CONFIG_SND_SOC_FSL_ASRC) += snd-soc-fsl-asrc.o
obj-$(CONFIG_SND_SOC_FSL_SAI) += snd-soc-fsl-sai.o
obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o
obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
new file mode 100644
index 0000000..867653b
--- /dev/null
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -0,0 +1,1031 @@
+/*
+ * Freescale ASRC ALSA SoC Digital Audio Interface (DAI) driver
+ *
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * Author: Nicolin Chen <nicoleotsuka@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_data/dma-imx.h>
+#include <linux/pm_runtime.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/pcm_params.h>
+
+#include "fsl_asrc.h"
+
+#define IDEAL_RATIO_DECIMAL_DEPTH 26
+
+#define pair_err(fmt, ...) \
+ dev_err(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__)
+
+#define pair_dbg(fmt, ...) \
+ dev_dbg(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__)
+
+/* Sample rates are aligned with that defined in pcm.h file */
+static const u8 process_option[][8][2] = {
+ /* 32kHz 44.1kHz 48kHz 64kHz 88.2kHz 96kHz 176kHz 192kHz */
+ {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 5512Hz */
+ {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 8kHz */
+ {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 11025Hz */
+ {{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 16kHz */
+ {{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 22050Hz */
+ {{0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0},}, /* 32kHz */
+ {{0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 44.1kHz */
+ {{0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 48kHz */
+ {{1, 2}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0},}, /* 64kHz */
+ {{1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 88.2kHz */
+ {{1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 96kHz */
+ {{2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 176kHz */
+ {{2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 192kHz */
+};
+
+/* Corresponding to process_option */
+static int supported_input_rate[] = {
+ 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200,
+ 96000, 176400, 192000,
+};
+
+static int supported_asrc_rate[] = {
+ 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000,
+};
+
+/**
+ * The following tables map the relationship between asrc_inclk/asrc_outclk in
+ * fsl_asrc.h and the registers of ASRCSR
+ */
+static unsigned char input_clk_map_v1[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
+};
+
+static unsigned char output_clk_map_v1[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
+};
+
+/* V2 uses the same map for input and output */
+static unsigned char input_clk_map_v2[] = {
+/* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf */
+ 0x0, 0x1, 0x2, 0x7, 0x4, 0x5, 0x6, 0x3, 0x8, 0x9, 0xa, 0xb, 0xc, 0xf, 0xe, 0xd,
+};
+
+static unsigned char output_clk_map_v2[] = {
+/* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf */
+ 0x8, 0x9, 0xa, 0x7, 0xc, 0x5, 0x6, 0xb, 0x0, 0x1, 0x2, 0x3, 0x4, 0xf, 0xe, 0xd,
+};
+
+static unsigned char *clk_map[2];
+
+enum fsl_asrc_type {
+ IMX35_ASRC,
+ IMX53_ASRC,
+};
+
+static const struct platform_device_id fsl_asrc_devtype[] = {
+ {
+ .name = "imx35-asrc",
+ .driver_data = IMX35_ASRC,
+ }, {
+ .name = "imx53-asrc",
+ .driver_data = IMX53_ASRC,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(platform, fsl_asrc_devtype);
+
+static const struct of_device_id fsl_asrc_ids[] = {
+ {
+ .compatible = "fsl,imx35-asrc",
+ .data = &fsl_asrc_devtype[IMX35_ASRC],
+ }, {
+ .compatible = "fsl,imx53-asrc",
+ .data = &fsl_asrc_devtype[IMX53_ASRC],
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(of, fsl_asrc_ids);
+
+static irqreturn_t fsl_asrc_isr(int irq, void *dev_id)
+{
+ struct fsl_asrc *asrc_priv = (struct fsl_asrc *)dev_id;
+ struct device *dev = &asrc_priv->pdev->dev;
+ enum asrc_pair_index index;
+ u32 status;
+
+ regmap_read(asrc_priv->regmap, REG_ASRSTR, &status);
+
+ /* Clean overload error */
+ regmap_write(asrc_priv->regmap, REG_ASRSTR, ASRSTR_AOLE);
+
+ /*
+ * We here use dev_dbg() for all exceptions because ASRC itself does
+ * not care if FIFO overflowed or underrun while a warning in the
+ * interrupt would result a ridged conversion.
+ */
+ for (index = ASRC_PAIR_A; index < ASRC_PAIR_MAX_NUM; index++) {
+ if (!asrc_priv->pair[index])
+ continue;
+
+ if (status & ASRSTR_ATQOL) {
+ asrc_priv->pair[index]->error |= ASRC_TASK_Q_OVERLOAD;
+ dev_dbg(dev, "ASRC Task Queue FIFO overload");
+ }
+
+ if (status & ASRSTR_AOOL(index)) {
+ asrc_priv->pair[index]->error |= ASRC_OUTPUT_TASK_OVERLOAD;
+ pair_dbg("Output Task Overload");
+ }
+
+ if (status & ASRSTR_AIOL(index)) {
+ asrc_priv->pair[index]->error |= ASRC_INPUT_TASK_OVERLOAD;
+ pair_dbg("Input Task Overload");
+ }
+
+ if (status & ASRSTR_AODO(index)) {
+ asrc_priv->pair[index]->error |= ASRC_OUTPUT_BUFFER_OVERFLOW;
+ pair_dbg("Output Data Buffer has overflowed");
+ }
+
+ if (status & ASRSTR_AIDU(index)) {
+ asrc_priv->pair[index]->error |= ASRC_INPUT_BUFFER_UNDERRUN;
+ pair_dbg("Input Data Buffer has underflowed");
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * Request ASRC pair
+ *
+ * It assigns pair by the order of A->C->B because allocation of pair B,
+ * within range [ANCA, ANCA+ANCB-1], depends on the channels of pair A
+ * while pair A and pair C are comparatively independent.
+ */
+static int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair)
+{
+ enum asrc_pair_index index = ASRC_INVALID_PAIR;
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ struct device *dev = &asrc_priv->pdev->dev;
+ unsigned long lock_flags;
+ int i, ret = 0;
+
+ spin_lock_irqsave(&asrc_priv->lock, lock_flags);
+
+ for (i = ASRC_PAIR_A; i < ASRC_PAIR_MAX_NUM; i++) {
+ if (asrc_priv->pair[i] != NULL)
+ continue;
+
+ index = i;
+
+ if (i != ASRC_PAIR_B)
+ break;
+ }
+
+ if (index == ASRC_INVALID_PAIR) {
+ dev_err(dev, "all pairs are busy now\n");
+ ret = -EBUSY;
+ } else if (asrc_priv->channel_avail < channels) {
+ dev_err(dev, "can't afford required channels: %d\n", channels);
+ ret = -EINVAL;
+ } else {
+ asrc_priv->channel_avail -= channels;
+ asrc_priv->pair[index] = pair;
+ pair->channels = channels;
+ pair->index = index;
+ }
+
+ spin_unlock_irqrestore(&asrc_priv->lock, lock_flags);
+
+ return ret;
+}
+
+/**
+ * Release ASRC pair
+ *
+ * It clears the resource from asrc_priv and releases the occupied channels.
+ */
+static void fsl_asrc_release_pair(struct fsl_asrc_pair *pair)
+{
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ enum asrc_pair_index index = pair->index;
+ unsigned long lock_flags;
+
+ /* Make sure the pair is disabled */
+ regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
+ ASRCTR_ASRCEi_MASK(index), 0);
+
+ spin_lock_irqsave(&asrc_priv->lock, lock_flags);
+
+ asrc_priv->channel_avail += pair->channels;
+ asrc_priv->pair[index] = NULL;
+ pair->error = 0;
+
+ spin_unlock_irqrestore(&asrc_priv->lock, lock_flags);
+}
+
+/**
+ * Configure input and output thresholds
+ */
+static int fsl_asrc_set_watermarks(struct fsl_asrc_pair *pair, u32 in, u32 out)
+{
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ enum asrc_pair_index index = pair->index;
+
+ regmap_update_bits(asrc_priv->regmap, REG_ASRMCR(index),
+ ASRMCRi_EXTTHRSHi_MASK |
+ ASRMCRi_INFIFO_THRESHOLD_MASK |
+ ASRMCRi_OUTFIFO_THRESHOLD_MASK,
+ ASRMCRi_EXTTHRSHi |
+ ASRMCRi_INFIFO_THRESHOLD(in) |
+ ASRMCRi_OUTFIFO_THRESHOLD(out));
+
+ return 0;
+}
+
+/**
+ * Calculate the total divisor between asrck clock rate and sample rate
+ *
+ * It follows the formula clk_rate = samplerate * (2 ^ prescaler) * divider
+ */
+static u32 fsl_asrc_cal_asrck_divisor(struct fsl_asrc_pair *pair, u32 div)
+{
+ u32 ps;
+
+ /* Calculate the divisors: prescaler [2^0, 2^7], divder [1, 8] */
+ for (ps = 0; div > 8; ps++)
+ div >>= 1;
+
+ return ((div - 1) << ASRCDRi_AxCPi_WIDTH) | ps;
+}
+
+/**
+ * Calculate and set the ratio for Ideal Ratio mode only
+ *
+ * The ratio is a 32-bit fixed point value with 26 fractional bits.
+ */
+static int fsl_asrc_set_ideal_ratio(struct fsl_asrc_pair *pair,
+ int inrate, int outrate)
+{
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ enum asrc_pair_index index = pair->index;
+ unsigned long ratio;
+ int i;
+
+ if (!outrate) {
+ pair_err("output rate should not be zero\n");
+ return -EINVAL;
+ }
+
+ /* Calculate the intergal part of the ratio */
+ ratio = (inrate / outrate) << IDEAL_RATIO_DECIMAL_DEPTH;
+
+ /* ... and then the 26 depth decimal part */
+ inrate %= outrate;
+
+ for (i = 1; i <= IDEAL_RATIO_DECIMAL_DEPTH; i++) {
+ inrate <<= 1;
+
+ if (inrate < outrate)
+ continue;
+
+ ratio |= 1 << (IDEAL_RATIO_DECIMAL_DEPTH - i);
+ inrate -= outrate;
+
+ if (!inrate)
+ break;
+ }
+
+ regmap_write(asrc_priv->regmap, REG_ASRIDRL(index), ratio);
+ regmap_write(asrc_priv->regmap, REG_ASRIDRH(index), ratio >> 24);
+
+ return 0;
+}
+
+/**
+ * Configure the assigned ASRC pair
+ *
+ * It configures those ASRC registers according to a configuration instance
+ * of struct asrc_config which includes in/output sample rate, width, channel
+ * and clock settings.
+ */
+static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair)
+{
+ struct asrc_config *config = pair->config;
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ enum asrc_pair_index index = pair->index;
+ u32 inrate = config->input_sample_rate, indiv;
+ u32 outrate = config->output_sample_rate, outdiv;
+ bool ideal = config->inclk == INCLK_NONE;
+ u32 clk_index[2], div[2];
+ int in, out, channels;
+ struct clk *clk;
+
+ if (!config) {
+ pair_err("invalid pair config\n");
+ return -EINVAL;
+ }
+
+ /* Validate channels */
+ if (config->channel_num < 1 || config->channel_num > 10) {
+ pair_err("does not support %d channels\n", config->channel_num);
+ return -EINVAL;
+ }
+
+ /* Validate output width */
+ if (config->output_word_width == ASRC_WIDTH_8_BIT) {
+ pair_err("does not support 8bit width output\n");
+ return -EINVAL;
+ }
+
+ /* Validate input and output sample rates */
+ for (in = 0; in < ARRAY_SIZE(supported_input_rate); in++)
+ if (inrate == supported_input_rate[in])
+ break;
+
+ if (in == ARRAY_SIZE(supported_input_rate)) {
+ pair_err("unsupported input sample rate: %dHz\n", inrate);
+ return -EINVAL;
+ }
+
+ for (out = 0; out < ARRAY_SIZE(supported_asrc_rate); out++)
+ if (outrate == supported_asrc_rate[out])
+ break;
+
+ if (out == ARRAY_SIZE(supported_asrc_rate)) {
+ pair_err("unsupported output sample rate: %dHz\n", outrate);
+ return -EINVAL;
+ }
+
+ /* Validate input and output clock sources */
+ clk_index[IN] = clk_map[IN][config->inclk];
+ clk_index[OUT] = clk_map[OUT][config->outclk];
+
+ /* We only have output clock for ideal ratio mode */
+ clk = asrc_priv->asrck_clk[clk_index[ideal ? OUT : IN]];
+
+ div[IN] = clk_get_rate(clk) / inrate;
+ if (div[IN] == 0) {
+ pair_err("failed to support input sample rate %dHz by asrck_%x",
+ inrate, clk_index[ideal ? OUT : IN]);
+ return -EINVAL;
+ }
+
+ clk = asrc_priv->asrck_clk[clk_index[OUT]];
+
+ /* Use fixed output rate for Ideal Ratio mode (INCLK_NONE) */
+ if (ideal)
+ div[OUT] = clk_get_rate(clk) / IDEAL_RATIO_RATE;
+ else
+ div[OUT] = clk_get_rate(clk) / outrate;
+
+ if (div[OUT] == 0) {
+ pair_err("failed to support output sample rate %dHz by asrck_%x",
+ outrate, clk_index[OUT]);
+ return -EINVAL;
+ }
+
+ /* Set the channel number */
+ channels = config->channel_num;
+
+ if (asrc_priv->channel_bits < 4)
+ channels /= 2;
+
+ /* Update channels for current pair */
+ regmap_update_bits(asrc_priv->regmap, REG_ASRCNCR,
+ ASRCNCR_ANCi_MASK(index, asrc_priv->channel_bits),
+ ASRCNCR_ANCi(index, channels, asrc_priv->channel_bits));
+
+ /* Default setting: Automatic selection for processing mode */
+ regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
+ ASRCTR_ATSi_MASK(index), ASRCTR_ATS(index));
+ regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
+ ASRCTR_USRi_MASK(index), 0);
+
+ /* Set the input and output clock sources */
+ regmap_update_bits(asrc_priv->regmap, REG_ASRCSR,
+ ASRCSR_AICSi_MASK(index) | ASRCSR_AOCSi_MASK(index),
+ ASRCSR_AICS(index, clk_index[IN]) |
+ ASRCSR_AOCS(index, clk_index[OUT]));
+
+ /* Calculate the input clock divisors */
+ indiv = fsl_asrc_cal_asrck_divisor(pair, div[IN]);
+ outdiv = fsl_asrc_cal_asrck_divisor(pair, div[OUT]);
+
+ /* Suppose indiv and outdiv includes prescaler, so add its MASK too */
+ regmap_update_bits(asrc_priv->regmap, REG_ASRCDR(index),
+ ASRCDRi_AOCPi_MASK(index) | ASRCDRi_AICPi_MASK(index) |
+ ASRCDRi_AOCDi_MASK(index) | ASRCDRi_AICDi_MASK(index),
+ ASRCDRi_AOCP(index, outdiv) | ASRCDRi_AICP(index, indiv));
+
+ /* Implement word_width configurations */
+ regmap_update_bits(asrc_priv->regmap, REG_ASRMCR1(index),
+ ASRMCR1i_OW16_MASK | ASRMCR1i_IWD_MASK,
+ ASRMCR1i_OW16(config->output_word_width) |
+ ASRMCR1i_IWD(config->input_word_width));
+
+ /* Enable BUFFER STALL */
+ regmap_update_bits(asrc_priv->regmap, REG_ASRMCR(index),
+ ASRMCRi_BUFSTALLi_MASK, ASRMCRi_BUFSTALLi);
+
+ /* Set default thresholds for input and output FIFO */
+ fsl_asrc_set_watermarks(pair, ASRC_INPUTFIFO_THRESHOLD,
+ ASRC_INPUTFIFO_THRESHOLD);
+
+ /* Configure the followings only for Ideal Ratio mode */
+ if (!ideal)
+ return 0;
+
+ /* Clear ASTSx bit to use Ideal Ratio mode */
+ regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
+ ASRCTR_ATSi_MASK(index), 0);
+
+ /* Enable Ideal Ratio mode */
+ regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
+ ASRCTR_IDRi_MASK(index) | ASRCTR_USRi_MASK(index),
+ ASRCTR_IDR(index) | ASRCTR_USR(index));
+
+ /* Apply configurations for pre- and post-processing */
+ regmap_update_bits(asrc_priv->regmap, REG_ASRCFG,
+ ASRCFG_PREMODi_MASK(index) | ASRCFG_POSTMODi_MASK(index),
+ ASRCFG_PREMOD(index, process_option[in][out][0]) |
+ ASRCFG_POSTMOD(index, process_option[in][out][1]));
+
+ return fsl_asrc_set_ideal_ratio(pair, inrate, outrate);
+}
+
+/**
+ * Start the assigned ASRC pair
+ *
+ * It enables the assigned pair and makes it stopped at the stall level.
+ */
+static void fsl_asrc_start_pair(struct fsl_asrc_pair *pair)
+{
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ enum asrc_pair_index index = pair->index;
+ int reg, retry = 10, i;
+
+ /* Enable the current pair */
+ regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
+ ASRCTR_ASRCEi_MASK(index), ASRCTR_ASRCE(index));
+
+ /* Wait for status of initialization */
+ do {
+ udelay(5);
+ regmap_read(asrc_priv->regmap, REG_ASRCFG, ®);
+ reg &= ASRCFG_INIRQi_MASK(index);
+ } while (!reg && --retry);
+
+ /* Make the input fifo to ASRC STALL level */
+ regmap_read(asrc_priv->regmap, REG_ASRCNCR, ®);
+ for (i = 0; i < pair->channels * 4; i++)
+ regmap_write(asrc_priv->regmap, REG_ASRDI(index), 0);
+
+ /* Enable overload interrupt */
+ regmap_write(asrc_priv->regmap, REG_ASRIER, ASRIER_AOLIE);
+}
+
+/**
+ * Stop the assigned ASRC pair
+ */
+static void fsl_asrc_stop_pair(struct fsl_asrc_pair *pair)
+{
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ enum asrc_pair_index index = pair->index;
+
+ /* Stop the current pair */
+ regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
+ ASRCTR_ASRCEi_MASK(index), 0);
+}
+
+/**
+ * Get DMA channel according to the pair and direction.
+ */
+struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir)
+{
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ enum asrc_pair_index index = pair->index;
+ char name[4];
+
+ sprintf(name, "%cx%c", dir == IN ? 'r' : 't', index + 'a');
+
+ return dma_request_slave_channel(&asrc_priv->pdev->dev, name);
+}
+EXPORT_SYMBOL_GPL(fsl_asrc_get_dma_channel);
+
+static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(dai);
+ int width = snd_pcm_format_width(params_format(params));
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct fsl_asrc_pair *pair = runtime->private_data;
+ unsigned int channels = params_channels(params);
+ unsigned int rate = params_rate(params);
+ struct asrc_config config;
+ int word_width, ret;
+
+ ret = fsl_asrc_request_pair(channels, pair);
+ if (ret) {
+ dev_err(dai->dev, "fail to request asrc pair\n");
+ return ret;
+ }
+
+ pair->config = &config;
+
+ if (width == 16)
+ width = ASRC_WIDTH_16_BIT;
+ else
+ width = ASRC_WIDTH_24_BIT;
+
+ if (asrc_priv->asrc_width == 16)
+ word_width = ASRC_WIDTH_16_BIT;
+ else
+ word_width = ASRC_WIDTH_24_BIT;
+
+ config.pair = pair->index;
+ config.channel_num = channels;
+ config.inclk = INCLK_NONE;
+ config.outclk = OUTCLK_ASRCK1_CLK;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ config.input_word_width = width;
+ config.output_word_width = word_width;
+ config.input_sample_rate = rate;
+ config.output_sample_rate = asrc_priv->asrc_rate;
+ } else {
+ config.input_word_width = word_width;
+ config.output_word_width = width;
+ config.input_sample_rate = asrc_priv->asrc_rate;
+ config.output_sample_rate = rate;
+ }
+
+ ret = fsl_asrc_config_pair(pair);
+ if (ret) {
+ dev_err(dai->dev, "fail to config asrc pair\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int fsl_asrc_dai_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct fsl_asrc_pair *pair = runtime->private_data;
+
+ if (pair)
+ fsl_asrc_release_pair(pair);
+
+ return 0;
+}
+
+static int fsl_asrc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct fsl_asrc_pair *pair = runtime->private_data;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ fsl_asrc_start_pair(pair);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ fsl_asrc_stop_pair(pair);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct snd_soc_dai_ops fsl_asrc_dai_ops = {
+ .hw_params = fsl_asrc_dai_hw_params,
+ .hw_free = fsl_asrc_dai_hw_free,
+ .trigger = fsl_asrc_dai_trigger,
+};
+
+static int fsl_asrc_dai_probe(struct snd_soc_dai *dai)
+{
+ struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(dai);
+
+ snd_soc_dai_init_dma_data(dai, &asrc_priv->dma_params_tx,
+ &asrc_priv->dma_params_rx);
+
+ return 0;
+}
+
+#define FSL_ASRC_RATES SNDRV_PCM_RATE_8000_192000
+#define FSL_ASRC_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FORMAT_S20_3LE)
+
+static struct snd_soc_dai_driver fsl_asrc_dai = {
+ .probe = fsl_asrc_dai_probe,
+ .playback = {
+ .stream_name = "ASRC-Playback",
+ .channels_min = 1,
+ .channels_max = 10,
+ .rates = FSL_ASRC_RATES,
+ .formats = FSL_ASRC_FORMATS,
+ },
+ .capture = {
+ .stream_name = "ASRC-Capture",
+ .channels_min = 1,
+ .channels_max = 10,
+ .rates = FSL_ASRC_RATES,
+ .formats = FSL_ASRC_FORMATS,
+ },
+ .ops = &fsl_asrc_dai_ops,
+};
+
+static const struct snd_soc_component_driver fsl_asrc_component = {
+ .name = "fsl-asrc-dai",
+};
+
+static bool fsl_asrc_readable_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case REG_ASRCTR:
+ case REG_ASRIER:
+ case REG_ASRCNCR:
+ case REG_ASRCFG:
+ case REG_ASRCSR:
+ case REG_ASRCDR1:
+ case REG_ASRCDR2:
+ case REG_ASRSTR:
+ case REG_ASRPM1:
+ case REG_ASRPM2:
+ case REG_ASRPM3:
+ case REG_ASRPM4:
+ case REG_ASRPM5:
+ case REG_ASRTFR1:
+ case REG_ASRCCR:
+ case REG_ASRDOA:
+ case REG_ASRDOB:
+ case REG_ASRDOC:
+ case REG_ASRIDRHA:
+ case REG_ASRIDRLA:
+ case REG_ASRIDRHB:
+ case REG_ASRIDRLB:
+ case REG_ASRIDRHC:
+ case REG_ASRIDRLC:
+ case REG_ASR76K:
+ case REG_ASR56K:
+ case REG_ASRMCRA:
+ case REG_ASRFSTA:
+ case REG_ASRMCRB:
+ case REG_ASRFSTB:
+ case REG_ASRMCRC:
+ case REG_ASRFSTC:
+ case REG_ASRMCR1A:
+ case REG_ASRMCR1B:
+ case REG_ASRMCR1C:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool fsl_asrc_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case REG_ASRSTR:
+ case REG_ASRDIA:
+ case REG_ASRDIB:
+ case REG_ASRDIC:
+ case REG_ASRDOA:
+ case REG_ASRDOB:
+ case REG_ASRDOC:
+ case REG_ASRFSTA:
+ case REG_ASRFSTB:
+ case REG_ASRFSTC:
+ case REG_ASRCFG:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool fsl_asrc_writeable_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case REG_ASRCTR:
+ case REG_ASRIER:
+ case REG_ASRCNCR:
+ case REG_ASRCFG:
+ case REG_ASRCSR:
+ case REG_ASRCDR1:
+ case REG_ASRCDR2:
+ case REG_ASRSTR:
+ case REG_ASRPM1:
+ case REG_ASRPM2:
+ case REG_ASRPM3:
+ case REG_ASRPM4:
+ case REG_ASRPM5:
+ case REG_ASRTFR1:
+ case REG_ASRCCR:
+ case REG_ASRDIA:
+ case REG_ASRDIB:
+ case REG_ASRDIC:
+ case REG_ASRIDRHA:
+ case REG_ASRIDRLA:
+ case REG_ASRIDRHB:
+ case REG_ASRIDRLB:
+ case REG_ASRIDRHC:
+ case REG_ASRIDRLC:
+ case REG_ASR76K:
+ case REG_ASR56K:
+ case REG_ASRMCRA:
+ case REG_ASRMCRB:
+ case REG_ASRMCRC:
+ case REG_ASRMCR1A:
+ case REG_ASRMCR1B:
+ case REG_ASRMCR1C:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static struct regmap_config fsl_asrc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+
+ .max_register = REG_ASRMCR1C,
+ .readable_reg = fsl_asrc_readable_reg,
+ .volatile_reg = fsl_asrc_volatile_reg,
+ .writeable_reg = fsl_asrc_writeable_reg,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+/**
+ * Initialize ASRC registers with a default configurations
+ */
+static int fsl_asrc_init(struct fsl_asrc *asrc_priv)
+{
+ /* Halt ASRC internal FP when input FIFO needs data for pair A, B, C */
+ regmap_write(asrc_priv->regmap, REG_ASRCTR, ASRCTR_ASRCEN);
+
+ /* Disable interrupt by default */
+ regmap_write(asrc_priv->regmap, REG_ASRIER, 0x0);
+
+ /* Apply recommended settings for parameters from Reference Manual */
+ regmap_write(asrc_priv->regmap, REG_ASRPM1, 0x7fffff);
+ regmap_write(asrc_priv->regmap, REG_ASRPM2, 0x255555);
+ regmap_write(asrc_priv->regmap, REG_ASRPM3, 0xff7280);
+ regmap_write(asrc_priv->regmap, REG_ASRPM4, 0xff7280);
+ regmap_write(asrc_priv->regmap, REG_ASRPM5, 0xff7280);
+
+ /* Base address for task queue FIFO. Set to 0x7C */
+ regmap_update_bits(asrc_priv->regmap, REG_ASRTFR1,
+ ASRTFR1_TF_BASE_MASK, ASRTFR1_TF_BASE(0xfc));
+
+ /* Set the processing clock for 76KHz to 133M */
+ regmap_write(asrc_priv->regmap, REG_ASR76K, 0x06D6);
+
+ /* Set the processing clock for 56KHz to 133M */
+ regmap_write(asrc_priv->regmap, REG_ASR56K, 0x0947);
+
+ return 0;
+}
+
+static int fsl_asrc_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *of_id =
+ of_match_device(fsl_asrc_ids, &pdev->dev);
+ struct device_node *np = pdev->dev.of_node;
+ struct fsl_asrc *asrc_priv;
+ enum fsl_asrc_type devtype;
+ struct resource *res;
+ void __iomem *regs;
+ int irq, ret, i;
+ char tmp[16];
+
+ asrc_priv = devm_kzalloc(&pdev->dev, sizeof(*asrc_priv), GFP_KERNEL);
+ if (!asrc_priv)
+ return -ENOMEM;
+
+ if (of_id)
+ pdev->id_entry = of_id->data;
+ devtype = pdev->id_entry->driver_data;
+
+ switch (devtype) {
+ case IMX35_ASRC:
+ asrc_priv->channel_bits = 3;
+ clk_map[IN] = input_clk_map_v1;
+ clk_map[OUT] = output_clk_map_v1;
+ break;
+ case IMX53_ASRC:
+ asrc_priv->channel_bits = 4;
+ clk_map[IN] = input_clk_map_v2;
+ clk_map[OUT] = output_clk_map_v2;
+ break;
+ default:
+ dev_err(&pdev->dev, "unsupported device type\n");
+ return -EINVAL;
+ }
+
+ asrc_priv->pdev = pdev;
+ strcpy(asrc_priv->name, np->name);
+
+ /* Get the addresses and IRQ */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(regs))
+ return PTR_ERR(regs);
+
+ asrc_priv->paddr = res->start;
+
+ /* Register regmap and let it prepare core clock */
+ if (of_property_read_bool(np, "big-endian"))
+ fsl_asrc_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG;
+
+ asrc_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
+ "mem", regs, &fsl_asrc_regmap_config);
+ if (IS_ERR(asrc_priv->regmap)) {
+ dev_err(&pdev->dev, "failed to init regmap\n");
+ return PTR_ERR(asrc_priv->regmap);
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
+ return irq;
+ }
+
+ ret = devm_request_irq(&pdev->dev, irq, fsl_asrc_isr, 0,
+ asrc_priv->name, asrc_priv);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to claim irq %u: %d\n", irq, ret);
+ return ret;
+ }
+
+ asrc_priv->mem_clk = devm_clk_get(&pdev->dev, "mem");
+ if (IS_ERR(asrc_priv->mem_clk)) {
+ dev_err(&pdev->dev, "failed to get mem clock\n");
+ return PTR_ERR(asrc_priv->ipg_clk);
+ }
+
+ asrc_priv->ipg_clk = devm_clk_get(&pdev->dev, "ipg");
+ if (IS_ERR(asrc_priv->ipg_clk)) {
+ dev_err(&pdev->dev, "failed to get ipg clock\n");
+ return PTR_ERR(asrc_priv->ipg_clk);
+ }
+
+ for (i = 0; i < ASRC_CLK_MAX_NUM; i++) {
+ sprintf(tmp, "asrck_%x", i);
+ asrc_priv->asrck_clk[i] = devm_clk_get(&pdev->dev, tmp);
+ if (IS_ERR(asrc_priv->asrck_clk[i])) {
+ dev_err(&pdev->dev, "failed to get %s clock\n", tmp);
+ return PTR_ERR(asrc_priv->asrck_clk[i]);
+ }
+ }
+
+ ret = fsl_asrc_init(asrc_priv);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to init asrc %d\n", ret);
+ return -EINVAL;
+ }
+
+ asrc_priv->channel_avail = 10;
+
+ ret = of_property_read_u32(np, "fsl,asrc-rate",
+ &asrc_priv->asrc_rate);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get output rate\n");
+ return -EINVAL;
+ }
+
+ ret = of_property_read_u32(np, "fsl,asrc-width",
+ &asrc_priv->asrc_width);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get output width\n");
+ return -EINVAL;
+ }
+
+ if (asrc_priv->asrc_width != 16 && asrc_priv->asrc_width != 24) {
+ dev_warn(&pdev->dev, "unsupported width, switching to 24bit\n");
+ asrc_priv->asrc_width = 24;
+ }
+
+ platform_set_drvdata(pdev, asrc_priv);
+ pm_runtime_enable(&pdev->dev);
+ spin_lock_init(&asrc_priv->lock);
+
+ ret = devm_snd_soc_register_component(&pdev->dev, &fsl_asrc_component,
+ &fsl_asrc_dai, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register ASoC DAI\n");
+ return ret;
+ }
+
+ ret = devm_snd_soc_register_platform(&pdev->dev, &fsl_asrc_platform);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register ASoC platform\n");
+ return ret;
+ }
+
+ dev_info(&pdev->dev, "driver registered\n");
+
+ return 0;
+}
+
+#if CONFIG_PM_RUNTIME
+static int fsl_asrc_runtime_resume(struct device *dev)
+{
+ struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
+ int i;
+
+ clk_prepare_enable(asrc_priv->mem_clk);
+ clk_prepare_enable(asrc_priv->ipg_clk);
+ for (i = 0; i < ASRC_CLK_MAX_NUM; i++)
+ clk_prepare_enable(asrc_priv->asrck_clk[i]);
+
+ return 0;
+}
+
+static int fsl_asrc_runtime_suspend(struct device *dev)
+{
+ struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
+ int i;
+
+ for (i = 0; i < ASRC_CLK_MAX_NUM; i++)
+ clk_disable_unprepare(asrc_priv->asrck_clk[i]);
+ clk_disable_unprepare(asrc_priv->ipg_clk);
+ clk_disable_unprepare(asrc_priv->mem_clk);
+
+ return 0;
+}
+#endif /* CONFIG_PM_RUNTIME */
+
+#if CONFIG_PM_SLEEP
+static int fsl_asrc_suspend(struct device *dev)
+{
+ struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
+
+ regcache_cache_only(asrc_priv->regmap, true);
+ regcache_mark_dirty(asrc_priv->regmap);
+
+ return 0;
+}
+
+static int fsl_asrc_resume(struct device *dev)
+{
+ struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
+ u32 asrctr;
+
+ /* Stop all pairs provisionally */
+ regmap_read(asrc_priv->regmap, REG_ASRCTR, &asrctr);
+ regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
+ ASRCTR_ASRCEi_ALL_MASK, 0);
+
+ /* Restore all registers */
+ regcache_cache_only(asrc_priv->regmap, false);
+ regcache_sync(asrc_priv->regmap);
+
+ /* Restart enabled pairs */
+ regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
+ ASRCTR_ASRCEi_ALL_MASK, asrctr);
+
+ return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static const struct dev_pm_ops fsl_asrc_pm = {
+ SET_RUNTIME_PM_OPS(fsl_asrc_runtime_suspend, fsl_asrc_runtime_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(fsl_asrc_suspend, fsl_asrc_resume)
+};
+
+static struct platform_driver fsl_asrc_driver = {
+ .probe = fsl_asrc_probe,
+ .driver = {
+ .name = "fsl-asrc",
+ .owner = THIS_MODULE,
+ .of_match_table = fsl_asrc_ids,
+ .pm = &fsl_asrc_pm,
+ },
+};
+module_platform_driver(fsl_asrc_driver);
+
+MODULE_DESCRIPTION("Freescale ASRC ASoC driver");
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_ALIAS("platform:fsl-asrc");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/fsl/fsl_asrc.h b/sound/soc/fsl/fsl_asrc.h
new file mode 100644
index 0000000..52fd4cd
--- /dev/null
+++ b/sound/soc/fsl/fsl_asrc.h
@@ -0,0 +1,431 @@
+/*
+ * fsl_asrc.h - Freescale ASRC ALSA SoC header file
+ *
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * Author: Nicolin Chen <nicoleotsuka@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef _FSL_ASRC_H
+#define _FSL_ASRC_H
+
+#define IN 0
+#define OUT 1
+
+#define ASRC_DMA_BUFFER_NUM 2
+#define ASRC_INPUTFIFO_THRESHOLD 32
+#define ASRC_OUTPUTFIFO_THRESHOLD 32
+#define ASRC_FIFO_THRESHOLD_MIN 0
+#define ASRC_FIFO_THRESHOLD_MAX 63
+#define ASRC_DMA_BUFFER_SIZE (1024 * 48 * 4)
+#define ASRC_MAX_BUFFER_SIZE (1024 * 48)
+#define ASRC_OUTPUT_LAST_SAMPLE 8
+
+#define IDEAL_RATIO_RATE 1000000
+
+#define REG_ASRCTR 0x00
+#define REG_ASRIER 0x04
+#define REG_ASRCNCR 0x0C
+#define REG_ASRCFG 0x10
+#define REG_ASRCSR 0x14
+
+#define REG_ASRCDR1 0x18
+#define REG_ASRCDR2 0x1C
+#define REG_ASRCDR(i) ((i < 2) ? REG_ASRCDR1 : REG_ASRCDR2)
+
+#define REG_ASRSTR 0x20
+#define REG_ASRRA 0x24
+#define REG_ASRRB 0x28
+#define REG_ASRRC 0x2C
+#define REG_ASRPM1 0x40
+#define REG_ASRPM2 0x44
+#define REG_ASRPM3 0x48
+#define REG_ASRPM4 0x4C
+#define REG_ASRPM5 0x50
+#define REG_ASRTFR1 0x54
+#define REG_ASRCCR 0x5C
+
+#define REG_ASRDIA 0x60
+#define REG_ASRDOA 0x64
+#define REG_ASRDIB 0x68
+#define REG_ASRDOB 0x6C
+#define REG_ASRDIC 0x70
+#define REG_ASRDOC 0x74
+#define REG_ASRDI(i) (REG_ASRDIA + (i << 3))
+#define REG_ASRDO(i) (REG_ASRDOA + (i << 3))
+#define REG_ASRDx(x, i) (x == IN ? REG_ASRDI(i) : REG_ASRDO(i))
+
+#define REG_ASRIDRHA 0x80
+#define REG_ASRIDRLA 0x84
+#define REG_ASRIDRHB 0x88
+#define REG_ASRIDRLB 0x8C
+#define REG_ASRIDRHC 0x90
+#define REG_ASRIDRLC 0x94
+#define REG_ASRIDRH(i) (REG_ASRIDRHA + (i << 3))
+#define REG_ASRIDRL(i) (REG_ASRIDRLA + (i << 3))
+
+#define REG_ASR76K 0x98
+#define REG_ASR56K 0x9C
+
+#define REG_ASRMCRA 0xA0
+#define REG_ASRFSTA 0xA4
+#define REG_ASRMCRB 0xA8
+#define REG_ASRFSTB 0xAC
+#define REG_ASRMCRC 0xB0
+#define REG_ASRFSTC 0xB4
+#define REG_ASRMCR(i) (REG_ASRMCRA + (i << 3))
+#define REG_ASRFST(i) (REG_ASRFSTA + (i << 3))
+
+#define REG_ASRMCR1A 0xC0
+#define REG_ASRMCR1B 0xC4
+#define REG_ASRMCR1C 0xC8
+#define REG_ASRMCR1(i) (REG_ASRMCR1A + (i << 2))
+
+
+/* REG0 0x00 REG_ASRCTR */
+#define ASRCTR_ATSi_SHIFT(i) (20 + i)
+#define ASRCTR_ATSi_MASK(i) (1 << ASRCTR_ATSi_SHIFT(i))
+#define ASRCTR_ATS(i) (1 << ASRCTR_ATSi_SHIFT(i))
+#define ASRCTR_USRi_SHIFT(i) (14 + (i << 1))
+#define ASRCTR_USRi_MASK(i) (1 << ASRCTR_USRi_SHIFT(i))
+#define ASRCTR_USR(i) (1 << ASRCTR_USRi_SHIFT(i))
+#define ASRCTR_IDRi_SHIFT(i) (13 + (i << 1))
+#define ASRCTR_IDRi_MASK(i) (1 << ASRCTR_IDRi_SHIFT(i))
+#define ASRCTR_IDR(i) (1 << ASRCTR_IDRi_SHIFT(i))
+#define ASRCTR_SRST_SHIFT 4
+#define ASRCTR_SRST_MASK (1 << ASRCTR_SRST_SHIFT)
+#define ASRCTR_SRST (1 << ASRCTR_SRST_SHIFT)
+#define ASRCTR_ASRCEi_SHIFT(i) (1 + i)
+#define ASRCTR_ASRCEi_MASK(i) (1 << ASRCTR_ASRCEi_SHIFT(i))
+#define ASRCTR_ASRCE(i) (1 << ASRCTR_ASRCEi_SHIFT(i))
+#define ASRCTR_ASRCEi_ALL_MASK (0x7 << ASRCTR_ASRCEi_SHIFT(0))
+#define ASRCTR_ASRCEN_SHIFT 0
+#define ASRCTR_ASRCEN_MASK (1 << ASRCTR_ASRCEN_SHIFT)
+#define ASRCTR_ASRCEN (1 << ASRCTR_ASRCEN_SHIFT)
+
+/* REG1 0x04 REG_ASRIER */
+#define ASRIER_AFPWE_SHIFT 7
+#define ASRIER_AFPWE_MASK (1 << ASRIER_AFPWE_SHIFT)
+#define ASRIER_AFPWE (1 << ASRIER_AFPWE_SHIFT)
+#define ASRIER_AOLIE_SHIFT 6
+#define ASRIER_AOLIE_MASK (1 << ASRIER_AOLIE_SHIFT)
+#define ASRIER_AOLIE (1 << ASRIER_AOLIE_SHIFT)
+#define ASRIER_ADOEi_SHIFT(i) (3 + i)
+#define ASRIER_ADOEi_MASK(i) (1 << ASRIER_ADOEi_SHIFT(i))
+#define ASRIER_ADOE(i) (1 << ASRIER_ADOEi_SHIFT(i))
+#define ASRIER_ADIEi_SHIFT(i) (0 + i)
+#define ASRIER_ADIEi_MASK(i) (1 << ASRIER_ADIEi_SHIFT(i))
+#define ASRIER_ADIE(i) (1 << ASRIER_ADIEi_SHIFT(i))
+
+/* REG2 0x0C REG_ASRCNCR */
+#define ASRCNCR_ANCi_SHIFT(i, b) (b * i)
+#define ASRCNCR_ANCi_MASK(i, b) (((1 << b) - 1) << ASRCNCR_ANCi_SHIFT(i, b))
+#define ASRCNCR_ANCi(i, v, b) ((v << ASRCNCR_ANCi_SHIFT(i, b)) & ASRCNCR_ANCi_MASK(i, b))
+
+/* REG3 0x10 REG_ASRCFG */
+#define ASRCFG_INIRQi_SHIFT(i) (21 + i)
+#define ASRCFG_INIRQi_MASK(i) (1 << ASRCFG_INIRQi_SHIFT(i))
+#define ASRCFG_INIRQi (1 << ASRCFG_INIRQi_SHIFT(i))
+#define ASRCFG_NDPRi_SHIFT(i) (18 + i)
+#define ASRCFG_NDPRi_MASK(i) (1 << ASRCFG_NDPRi_SHIFT(i))
+#define ASRCFG_NDPRi (1 << ASRCFG_NDPRi_SHIFT(i))
+#define ASRCFG_POSTMODi_SHIFT(i) (8 + (i << 2))
+#define ASRCFG_POSTMODi_WIDTH 2
+#define ASRCFG_POSTMODi_MASK(i) (((1 << ASRCFG_POSTMODi_WIDTH) - 1) << ASRCFG_POSTMODi_SHIFT(i))
+#define ASRCFG_POSTMOD(i, v) ((v) << ASRCFG_POSTMODi_SHIFT(i))
+#define ASRCFG_POSTMODi_UP(i) (0 << ASRCFG_POSTMODi_SHIFT(i))
+#define ASRCFG_POSTMODi_DCON(i) (1 << ASRCFG_POSTMODi_SHIFT(i))
+#define ASRCFG_POSTMODi_DOWN(i) (2 << ASRCFG_POSTMODi_SHIFT(i))
+#define ASRCFG_PREMODi_SHIFT(i) (6 + (i << 2))
+#define ASRCFG_PREMODi_WIDTH 2
+#define ASRCFG_PREMODi_MASK(i) (((1 << ASRCFG_PREMODi_WIDTH) - 1) << ASRCFG_PREMODi_SHIFT(i))
+#define ASRCFG_PREMOD(i, v) ((v) << ASRCFG_PREMODi_SHIFT(i))
+#define ASRCFG_PREMODi_UP(i) (0 << ASRCFG_PREMODi_SHIFT(i))
+#define ASRCFG_PREMODi_DCON(i) (1 << ASRCFG_PREMODi_SHIFT(i))
+#define ASRCFG_PREMODi_DOWN(i) (2 << ASRCFG_PREMODi_SHIFT(i))
+#define ASRCFG_PREMODi_BYPASS(i) (3 << ASRCFG_PREMODi_SHIFT(i))
+
+/* REG4 0x14 REG_ASRCSR */
+#define ASRCSR_AxCSi_WIDTH 4
+#define ASRCSR_AxCSi_MASK ((1 << ASRCSR_AxCSi_WIDTH) - 1)
+#define ASRCSR_AOCSi_SHIFT(i) (12 + (i << 2))
+#define ASRCSR_AOCSi_MASK(i) (((1 << ASRCSR_AxCSi_WIDTH) - 1) << ASRCSR_AOCSi_SHIFT(i))
+#define ASRCSR_AOCS(i, v) ((v) << ASRCSR_AOCSi_SHIFT(i))
+#define ASRCSR_AICSi_SHIFT(i) (i << 2)
+#define ASRCSR_AICSi_MASK(i) (((1 << ASRCSR_AxCSi_WIDTH) - 1) << ASRCSR_AICSi_SHIFT(i))
+#define ASRCSR_AICS(i, v) ((v) << ASRCSR_AICSi_SHIFT(i))
+
+/* REG5&6 0x18 & 0x1C REG_ASRCDR1 & ASRCDR2 */
+#define ASRCDRi_AxCPi_WIDTH 3
+#define ASRCDRi_AICPi_SHIFT(i) (0 + (i % 2) * 6)
+#define ASRCDRi_AICPi_MASK(i) (((1 << ASRCDRi_AxCPi_WIDTH) - 1) << ASRCDRi_AICPi_SHIFT(i))
+#define ASRCDRi_AICP(i, v) ((v) << ASRCDRi_AICPi_SHIFT(i))
+#define ASRCDRi_AICDi_SHIFT(i) (3 + (i % 2) * 6)
+#define ASRCDRi_AICDi_MASK(i) (((1 << ASRCDRi_AxCPi_WIDTH) - 1) << ASRCDRi_AICDi_SHIFT(i))
+#define ASRCDRi_AICD(i, v) ((v) << ASRCDRi_AICDi_SHIFT(i))
+#define ASRCDRi_AOCPi_SHIFT(i) ((i < 2) ? 12 + i * 6 : 6)
+#define ASRCDRi_AOCPi_MASK(i) (((1 << ASRCDRi_AxCPi_WIDTH) - 1) << ASRCDRi_AOCPi_SHIFT(i))
+#define ASRCDRi_AOCP(i, v) ((v) << ASRCDRi_AOCPi_SHIFT(i))
+#define ASRCDRi_AOCDi_SHIFT(i) ((i < 2) ? 15 + i * 6 : 9)
+#define ASRCDRi_AOCDi_MASK(i) (((1 << ASRCDRi_AxCPi_WIDTH) - 1) << ASRCDRi_AOCDi_SHIFT(i))
+#define ASRCDRi_AOCD(i, v) ((v) << ASRCDRi_AOCDi_SHIFT(i))
+
+/* REG7 0x20 REG_ASRSTR */
+#define ASRSTR_DSLCNT_SHIFT 21
+#define ASRSTR_DSLCNT_MASK (1 << ASRSTR_DSLCNT_SHIFT)
+#define ASRSTR_DSLCNT (1 << ASRSTR_DSLCNT_SHIFT)
+#define ASRSTR_ATQOL_SHIFT 20
+#define ASRSTR_ATQOL_MASK (1 << ASRSTR_ATQOL_SHIFT)
+#define ASRSTR_ATQOL (1 << ASRSTR_ATQOL_SHIFT)
+#define ASRSTR_AOOLi_SHIFT(i) (17 + i)
+#define ASRSTR_AOOLi_MASK(i) (1 << ASRSTR_AOOLi_SHIFT(i))
+#define ASRSTR_AOOL(i) (1 << ASRSTR_AOOLi_SHIFT(i))
+#define ASRSTR_AIOLi_SHIFT(i) (14 + i)
+#define ASRSTR_AIOLi_MASK(i) (1 << ASRSTR_AIOLi_SHIFT(i))
+#define ASRSTR_AIOL(i) (1 << ASRSTR_AIOLi_SHIFT(i))
+#define ASRSTR_AODOi_SHIFT(i) (11 + i)
+#define ASRSTR_AODOi_MASK(i) (1 << ASRSTR_AODOi_SHIFT(i))
+#define ASRSTR_AODO(i) (1 << ASRSTR_AODOi_SHIFT(i))
+#define ASRSTR_AIDUi_SHIFT(i) (8 + i)
+#define ASRSTR_AIDUi_MASK(i) (1 << ASRSTR_AIDUi_SHIFT(i))
+#define ASRSTR_AIDU(i) (1 << ASRSTR_AIDUi_SHIFT(i))
+#define ASRSTR_FPWT_SHIFT 7
+#define ASRSTR_FPWT_MASK (1 << ASRSTR_FPWT_SHIFT)
+#define ASRSTR_FPWT (1 << ASRSTR_FPWT_SHIFT)
+#define ASRSTR_AOLE_SHIFT 6
+#define ASRSTR_AOLE_MASK (1 << ASRSTR_AOLE_SHIFT)
+#define ASRSTR_AOLE (1 << ASRSTR_AOLE_SHIFT)
+#define ASRSTR_AODEi_SHIFT(i) (3 + i)
+#define ASRSTR_AODFi_MASK(i) (1 << ASRSTR_AODEi_SHIFT(i))
+#define ASRSTR_AODF(i) (1 << ASRSTR_AODEi_SHIFT(i))
+#define ASRSTR_AIDEi_SHIFT(i) (0 + i)
+#define ASRSTR_AIDEi_MASK(i) (1 << ASRSTR_AIDEi_SHIFT(i))
+#define ASRSTR_AIDE(i) (1 << ASRSTR_AIDEi_SHIFT(i))
+
+/* REG10 0x54 REG_ASRTFR1 */
+#define ASRTFR1_TF_BASE_WIDTH 7
+#define ASRTFR1_TF_BASE_SHIFT 6
+#define ASRTFR1_TF_BASE_MASK (((1 << ASRTFR1_TF_BASE_WIDTH) - 1) << ASRTFR1_TF_BASE_SHIFT)
+#define ASRTFR1_TF_BASE(i) ((i) << ASRTFR1_TF_BASE_SHIFT)
+
+/*
+ * REG22 0xA0 REG_ASRMCRA
+ * REG24 0xA8 REG_ASRMCRB
+ * REG26 0xB0 REG_ASRMCRC
+ */
+#define ASRMCRi_ZEROBUFi_SHIFT 23
+#define ASRMCRi_ZEROBUFi_MASK (1 << ASRMCRi_ZEROBUFi_SHIFT)
+#define ASRMCRi_ZEROBUFi (1 << ASRMCRi_ZEROBUFi_SHIFT)
+#define ASRMCRi_EXTTHRSHi_SHIFT 22
+#define ASRMCRi_EXTTHRSHi_MASK (1 << ASRMCRi_EXTTHRSHi_SHIFT)
+#define ASRMCRi_EXTTHRSHi (1 << ASRMCRi_EXTTHRSHi_SHIFT)
+#define ASRMCRi_BUFSTALLi_SHIFT 21
+#define ASRMCRi_BUFSTALLi_MASK (1 << ASRMCRi_BUFSTALLi_SHIFT)
+#define ASRMCRi_BUFSTALLi (1 << ASRMCRi_BUFSTALLi_SHIFT)
+#define ASRMCRi_BYPASSPOLYi_SHIFT 20
+#define ASRMCRi_BYPASSPOLYi_MASK (1 << ASRMCRi_BYPASSPOLYi_SHIFT)
+#define ASRMCRi_BYPASSPOLYi (1 << ASRMCRi_BYPASSPOLYi_SHIFT)
+#define ASRMCRi_OUTFIFO_THRESHOLD_WIDTH 6
+#define ASRMCRi_OUTFIFO_THRESHOLD_SHIFT 12
+#define ASRMCRi_OUTFIFO_THRESHOLD_MASK (((1 << ASRMCRi_OUTFIFO_THRESHOLD_WIDTH) - 1) << ASRMCRi_OUTFIFO_THRESHOLD_SHIFT)
+#define ASRMCRi_OUTFIFO_THRESHOLD(v) (((v) << ASRMCRi_OUTFIFO_THRESHOLD_SHIFT) & ASRMCRi_OUTFIFO_THRESHOLD_MASK)
+#define ASRMCRi_RSYNIFi_SHIFT 11
+#define ASRMCRi_RSYNIFi_MASK (1 << ASRMCRi_RSYNIFi_SHIFT)
+#define ASRMCRi_RSYNIFi (1 << ASRMCRi_RSYNIFi_SHIFT)
+#define ASRMCRi_RSYNOFi_SHIFT 10
+#define ASRMCRi_RSYNOFi_MASK (1 << ASRMCRi_RSYNOFi_SHIFT)
+#define ASRMCRi_RSYNOFi (1 << ASRMCRi_RSYNOFi_SHIFT)
+#define ASRMCRi_INFIFO_THRESHOLD_WIDTH 6
+#define ASRMCRi_INFIFO_THRESHOLD_SHIFT 0
+#define ASRMCRi_INFIFO_THRESHOLD_MASK (((1 << ASRMCRi_INFIFO_THRESHOLD_WIDTH) - 1) << ASRMCRi_INFIFO_THRESHOLD_SHIFT)
+#define ASRMCRi_INFIFO_THRESHOLD(v) (((v) << ASRMCRi_INFIFO_THRESHOLD_SHIFT) & ASRMCRi_INFIFO_THRESHOLD_MASK)
+
+/*
+ * REG23 0xA4 REG_ASRFSTA
+ * REG25 0xAC REG_ASRFSTB
+ * REG27 0xB4 REG_ASRFSTC
+ */
+#define ASRFSTi_OAFi_SHIFT 23
+#define ASRFSTi_OAFi_MASK (1 << ASRFSTi_OAFi_SHIFT)
+#define ASRFSTi_OAFi (1 << ASRFSTi_OAFi_SHIFT)
+#define ASRFSTi_OUTPUT_FIFO_WIDTH 7
+#define ASRFSTi_OUTPUT_FIFO_SHIFT 12
+#define ASRFSTi_OUTPUT_FIFO_MASK (((1 << ASRFSTi_OUTPUT_FIFO_WIDTH) - 1) << ASRFSTi_OUTPUT_FIFO_SHIFT)
+#define ASRFSTi_IAEi_SHIFT 11
+#define ASRFSTi_IAEi_MASK (1 << ASRFSTi_OAFi_SHIFT)
+#define ASRFSTi_IAEi (1 << ASRFSTi_OAFi_SHIFT)
+#define ASRFSTi_INPUT_FIFO_WIDTH 7
+#define ASRFSTi_INPUT_FIFO_SHIFT 0
+#define ASRFSTi_INPUT_FIFO_MASK ((1 << ASRFSTi_INPUT_FIFO_WIDTH) - 1)
+
+/* REG28 0xC0 & 0xC4 & 0xC8 REG_ASRMCR1i */
+#define ASRMCR1i_IWD_WIDTH 3
+#define ASRMCR1i_IWD_SHIFT 9
+#define ASRMCR1i_IWD_MASK (((1 << ASRMCR1i_IWD_WIDTH) - 1) << ASRMCR1i_IWD_SHIFT)
+#define ASRMCR1i_IWD(v) ((v) << ASRMCR1i_IWD_SHIFT)
+#define ASRMCR1i_IMSB_SHIFT 8
+#define ASRMCR1i_IMSB_MASK (1 << ASRMCR1i_IMSB_SHIFT)
+#define ASRMCR1i_IMSB_MSB (1 << ASRMCR1i_IMSB_SHIFT)
+#define ASRMCR1i_IMSB_LSB (0 << ASRMCR1i_IMSB_SHIFT)
+#define ASRMCR1i_OMSB_SHIFT 2
+#define ASRMCR1i_OMSB_MASK (1 << ASRMCR1i_OMSB_SHIFT)
+#define ASRMCR1i_OMSB_MSB (1 << ASRMCR1i_OMSB_SHIFT)
+#define ASRMCR1i_OMSB_LSB (0 << ASRMCR1i_OMSB_SHIFT)
+#define ASRMCR1i_OSGN_SHIFT 1
+#define ASRMCR1i_OSGN_MASK (1 << ASRMCR1i_OSGN_SHIFT)
+#define ASRMCR1i_OSGN (1 << ASRMCR1i_OSGN_SHIFT)
+#define ASRMCR1i_OW16_SHIFT 0
+#define ASRMCR1i_OW16_MASK (1 << ASRMCR1i_OW16_SHIFT)
+#define ASRMCR1i_OW16(v) ((v) << ASRMCR1i_OW16_SHIFT)
+
+
+enum asrc_pair_index {
+ ASRC_INVALID_PAIR = -1,
+ ASRC_PAIR_A = 0,
+ ASRC_PAIR_B = 1,
+ ASRC_PAIR_C = 2,
+};
+
+#define ASRC_PAIR_MAX_NUM (ASRC_PAIR_C + 1)
+
+enum asrc_inclk {
+ INCLK_NONE = 0x03,
+ INCLK_ESAI_RX = 0x00,
+ INCLK_SSI1_RX = 0x01,
+ INCLK_SSI2_RX = 0x02,
+ INCLK_SSI3_RX = 0x07,
+ INCLK_SPDIF_RX = 0x04,
+ INCLK_MLB_CLK = 0x05,
+ INCLK_PAD = 0x06,
+ INCLK_ESAI_TX = 0x08,
+ INCLK_SSI1_TX = 0x09,
+ INCLK_SSI2_TX = 0x0a,
+ INCLK_SSI3_TX = 0x0b,
+ INCLK_SPDIF_TX = 0x0c,
+ INCLK_ASRCK1_CLK = 0x0f,
+};
+
+enum asrc_outclk {
+ OUTCLK_NONE = 0x03,
+ OUTCLK_ESAI_TX = 0x00,
+ OUTCLK_SSI1_TX = 0x01,
+ OUTCLK_SSI2_TX = 0x02,
+ OUTCLK_SSI3_TX = 0x07,
+ OUTCLK_SPDIF_TX = 0x04,
+ OUTCLK_MLB_CLK = 0x05,
+ OUTCLK_PAD = 0x06,
+ OUTCLK_ESAI_RX = 0x08,
+ OUTCLK_SSI1_RX = 0x09,
+ OUTCLK_SSI2_RX = 0x0a,
+ OUTCLK_SSI3_RX = 0x0b,
+ OUTCLK_SPDIF_RX = 0x0c,
+ OUTCLK_ASRCK1_CLK = 0x0f,
+};
+
+#define ASRC_CLK_MAX_NUM 16
+
+enum asrc_word_width {
+ ASRC_WIDTH_24_BIT = 0,
+ ASRC_WIDTH_16_BIT = 1,
+ ASRC_WIDTH_8_BIT = 2,
+};
+
+struct asrc_config {
+ enum asrc_pair_index pair;
+ unsigned int channel_num;
+ unsigned int buffer_num;
+ unsigned int dma_buffer_size;
+ unsigned int input_sample_rate;
+ unsigned int output_sample_rate;
+ enum asrc_word_width input_word_width;
+ enum asrc_word_width output_word_width;
+ enum asrc_inclk inclk;
+ enum asrc_outclk outclk;
+};
+
+struct asrc_req {
+ unsigned int chn_num;
+ enum asrc_pair_index index;
+};
+
+struct asrc_querybuf {
+ unsigned int buffer_index;
+ unsigned int input_length;
+ unsigned int output_length;
+ unsigned long input_offset;
+ unsigned long output_offset;
+};
+
+struct asrc_convert_buffer {
+ void *input_buffer_vaddr;
+ void *output_buffer_vaddr;
+ unsigned int input_buffer_length;
+ unsigned int output_buffer_length;
+};
+
+struct asrc_status_flags {
+ enum asrc_pair_index index;
+ unsigned int overload_error;
+};
+
+enum asrc_error_status {
+ ASRC_TASK_Q_OVERLOAD = 0x01,
+ ASRC_OUTPUT_TASK_OVERLOAD = 0x02,
+ ASRC_INPUT_TASK_OVERLOAD = 0x04,
+ ASRC_OUTPUT_BUFFER_OVERFLOW = 0x08,
+ ASRC_INPUT_BUFFER_UNDERRUN = 0x10,
+};
+
+struct dma_block {
+ dma_addr_t dma_paddr;
+ void *dma_vaddr;
+ unsigned int length;
+};
+
+struct fsl_asrc_pair {
+ struct fsl_asrc *asrc_priv;
+ struct asrc_config *config;
+ unsigned int error;
+ spinlock_t lock;
+
+ enum asrc_pair_index index;
+ unsigned int rate[2];
+ unsigned int channels;
+ enum asrc_word_width word_width[2];
+
+ struct dma_async_tx_descriptor *desc[2];
+ struct dma_chan *dma_chan[2];
+ struct imx_dma_data dma_data;
+ unsigned int pos;
+
+ void *private;
+};
+
+struct fsl_asrc {
+ struct snd_dmaengine_dai_dma_data dma_params_rx;
+ struct snd_dmaengine_dai_dma_data dma_params_tx;
+ struct platform_device *pdev;
+ struct regmap *regmap;
+ struct clk *mem_clk;
+ struct clk *ipg_clk;
+ struct clk *asrck_clk[ASRC_CLK_MAX_NUM];
+ spinlock_t lock;
+
+ struct fsl_asrc_pair *pair[ASRC_PAIR_MAX_NUM];
+ unsigned int channel_bits;
+ unsigned int channel_avail;
+ unsigned long paddr;
+
+ int asrc_rate;
+ int asrc_width;
+
+ char name[32];
+};
+
+extern struct snd_soc_platform_driver fsl_asrc_platform;
+struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir);
+#endif /* _FSL_ASRC_H */
diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c
new file mode 100644
index 0000000..c742a99
--- /dev/null
+++ b/sound/soc/fsl/fsl_asrc_dma.c
@@ -0,0 +1,385 @@
+/*
+ * Freescale ASRC ALSA SoC Platform (DMA) driver
+ *
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * Author: Nicolin Chen <nicoleotsuka@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/platform_data/dma-imx.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/pcm_params.h>
+
+#include "fsl_asrc.h"
+
+#define FSL_ASRC_DMABUF_SIZE (256 * 1024)
+
+static struct snd_pcm_hardware snd_imx_hardware = {
+ .info = SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_RESUME,
+ .buffer_bytes_max = FSL_ASRC_DMABUF_SIZE,
+ .period_bytes_min = 128,
+ .period_bytes_max = 65535, /* Limited by SDMA engine */
+ .periods_min = 2,
+ .periods_max = 255,
+ .fifo_size = 0,
+};
+
+static bool filter(struct dma_chan *chan, void *param)
+{
+ if (!imx_dma_is_general_purpose(chan))
+ return false;
+
+ chan->private = param;
+
+ return true;
+}
+
+static void fsl_asrc_dma_complete(void *arg)
+{
+ struct snd_pcm_substream *substream = arg;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct fsl_asrc_pair *pair = runtime->private_data;
+
+ pair->pos += snd_pcm_lib_period_bytes(substream);
+ if (pair->pos >= snd_pcm_lib_buffer_bytes(substream))
+ pair->pos = 0;
+
+ snd_pcm_period_elapsed(substream);
+}
+
+static int fsl_asrc_dma_prepare_and_submit(struct snd_pcm_substream *substream)
+{
+ u8 dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? OUT : IN;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct fsl_asrc_pair *pair = runtime->private_data;
+ struct device *dev = rtd->platform->dev;
+ unsigned long flags = DMA_CTRL_ACK;
+
+ /* Prepare and submit front-end DMA channel */
+ if (!substream->runtime->no_period_wakeup)
+ flags |= DMA_PREP_INTERRUPT;
+
+ pair->pos = 0;
+ pair->desc[!dir] = dmaengine_prep_dma_cyclic(
+ pair->dma_chan[!dir], runtime->dma_addr,
+ snd_pcm_lib_buffer_bytes(substream),
+ snd_pcm_lib_period_bytes(substream),
+ dir == OUT ? DMA_TO_DEVICE : DMA_FROM_DEVICE, flags);
+ if (!pair->desc[!dir]) {
+ dev_err(dev, "failed to prepare slave DMA for front-end\n");
+ return -ENOMEM;
+ }
+
+ pair->desc[!dir]->callback = fsl_asrc_dma_complete;
+ pair->desc[!dir]->callback_param = substream;
+
+ dmaengine_submit(pair->desc[!dir]);
+
+ /* Prepare and submit back-end DMA channel */
+ pair->desc[dir] = dmaengine_prep_dma_cyclic(
+ pair->dma_chan[dir], 0xffff, 64, 64, DMA_DEV_TO_DEV, 0);
+ if (!pair->desc[dir]) {
+ dev_err(dev, "failed to prepare slave DMA for back-end\n");
+ return -ENOMEM;
+ }
+
+ dmaengine_submit(pair->desc[dir]);
+
+ return 0;
+}
+
+static int fsl_asrc_dma_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct fsl_asrc_pair *pair = runtime->private_data;
+ int ret;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ ret = fsl_asrc_dma_prepare_and_submit(substream);
+ if (ret)
+ return ret;
+ dma_async_issue_pending(pair->dma_chan[IN]);
+ dma_async_issue_pending(pair->dma_chan[OUT]);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ dmaengine_terminate_all(pair->dma_chan[OUT]);
+ dmaengine_terminate_all(pair->dma_chan[IN]);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int fsl_asrc_dma_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ enum dma_slave_buswidth buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+ struct snd_dmaengine_dai_dma_data *dma_params_fe = NULL;
+ struct snd_dmaengine_dai_dma_data *dma_params_be = NULL;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct fsl_asrc_pair *pair = runtime->private_data;
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ struct dma_slave_config config_fe, config_be;
+ enum asrc_pair_index index = pair->index;
+ struct device *dev = rtd->platform->dev;
+ int stream = substream->stream;
+ struct imx_dma_data *tmp_data;
+ struct snd_soc_dpcm *dpcm;
+ struct dma_chan *tmp_chan;
+ struct device *dev_be;
+ u8 dir = tx ? OUT : IN;
+ dma_cap_mask_t mask;
+ int ret;
+
+ /* Fetch the back-end dma_data from DPCM */
+ list_for_each_entry(dpcm, &rtd->dpcm[stream].be_clients, list_be) {
+ struct snd_soc_pcm_runtime *be = dpcm->be;
+ struct snd_pcm_substream *substream_be;
+ struct snd_soc_dai *dai = be->cpu_dai;
+
+ if (dpcm->fe != rtd)
+ continue;
+
+ substream_be = snd_soc_dpcm_get_substream(be, stream);
+ dma_params_be = snd_soc_dai_get_dma_data(dai, substream_be);
+ dev_be = dai->dev;
+ break;
+ }
+
+ if (!dma_params_be) {
+ dev_err(dev, "failed to get the substream of back-end\n");
+ return -EINVAL;
+ }
+
+ /* Override dma_data of the front-end and config its dmaengine */
+ dma_params_fe = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+ dma_params_fe->addr = asrc_priv->paddr + REG_ASRDx(!dir, index);
+ dma_params_fe->maxburst = dma_params_be->maxburst;
+
+ pair->dma_chan[!dir] = fsl_asrc_get_dma_channel(pair, !dir);
+ if (!pair->dma_chan[!dir]) {
+ dev_err(dev, "failed to request DMA channel\n");
+ return -EINVAL;
+ }
+
+ memset(&config_fe, 0, sizeof(config_fe));
+ ret = snd_dmaengine_pcm_prepare_slave_config(substream, params, &config_fe);
+ if (ret) {
+ dev_err(dev, "failed to prepare DMA config for front-end\n");
+ return ret;
+ }
+
+ ret = dmaengine_slave_config(pair->dma_chan[!dir], &config_fe);
+ if (ret) {
+ dev_err(dev, "failed to config DMA channel for front-end\n");
+ return ret;
+ }
+
+ /* Request and config DMA channel for back-end */
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ dma_cap_set(DMA_CYCLIC, mask);
+
+ /* Get DMA request of back end */
+ tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
+ tmp_data = tmp_chan->private;
+ pair->dma_data.dma_request = tmp_data->dma_request;
+ dma_release_channel(tmp_chan);
+
+ /* Get DMA request of fore end */
+ tmp_chan = fsl_asrc_get_dma_channel(pair, dir);
+ tmp_data = tmp_chan->private;
+ pair->dma_data.dma_request2 = tmp_data->dma_request;
+ pair->dma_data.peripheral_type = tmp_data->peripheral_type;
+ pair->dma_data.priority = tmp_data->priority;
+ dma_release_channel(tmp_chan);
+
+ pair->dma_chan[dir] = dma_request_channel(mask, filter, &pair->dma_data);
+ if (!pair->dma_chan[dir]) {
+ dev_err(dev, "failed to request DMA channel for back-end\n");
+ return -EINVAL;
+ }
+
+ if (asrc_priv->asrc_width == 16)
+ buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ else
+ buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
+
+ config_be.direction = DMA_DEV_TO_DEV;
+ config_be.src_addr_width = buswidth;
+ config_be.src_maxburst = dma_params_be->maxburst;
+ config_be.dst_addr_width = buswidth;
+ config_be.dst_maxburst = dma_params_be->maxburst;
+
+ if (tx) {
+ config_be.src_addr = asrc_priv->paddr + REG_ASRDO(index);
+ config_be.dst_addr = dma_params_be->addr;
+ } else {
+ config_be.dst_addr = asrc_priv->paddr + REG_ASRDI(index);
+ config_be.src_addr = dma_params_be->addr;
+ }
+
+ ret = dmaengine_slave_config(pair->dma_chan[dir], &config_be);
+ if (ret) {
+ dev_err(dev, "failed to config DMA channel for back-end\n");
+ return ret;
+ }
+
+ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+
+ return 0;
+}
+
+static int fsl_asrc_dma_hw_free(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct fsl_asrc_pair *pair = runtime->private_data;
+
+ snd_pcm_set_runtime_buffer(substream, NULL);
+
+ if (pair->dma_chan[IN])
+ dma_release_channel(pair->dma_chan[IN]);
+
+ if (pair->dma_chan[OUT])
+ dma_release_channel(pair->dma_chan[OUT]);
+
+ pair->dma_chan[IN] = NULL;
+ pair->dma_chan[OUT] = NULL;
+
+ return 0;
+}
+
+static int fsl_asrc_dma_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct device *dev = rtd->platform->dev;
+ struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
+ struct fsl_asrc_pair *pair;
+
+ pair = kzalloc(sizeof(struct fsl_asrc_pair), GFP_KERNEL);
+ if (!pair) {
+ dev_err(dev, "failed to allocate pair\n");
+ return -ENOMEM;
+ }
+
+ pair->asrc_priv = asrc_priv;
+
+ spin_lock_init(&pair->lock);
+
+ runtime->private_data = pair;
+
+ snd_pcm_hw_constraint_integer(substream->runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
+
+ return 0;
+}
+
+static int fsl_asrc_dma_shutdown(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct fsl_asrc_pair *pair = runtime->private_data;
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+
+ if (pair && asrc_priv->pair[pair->index] == pair)
+ asrc_priv->pair[pair->index] = NULL;
+
+ kfree(pair);
+
+ return 0;
+}
+
+static snd_pcm_uframes_t fsl_asrc_dma_pcm_pointer(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct fsl_asrc_pair *pair = runtime->private_data;
+ return bytes_to_frames(substream->runtime, pair->pos);
+}
+
+static struct snd_pcm_ops fsl_asrc_dma_pcm_ops = {
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = fsl_asrc_dma_hw_params,
+ .hw_free = fsl_asrc_dma_hw_free,
+ .trigger = fsl_asrc_dma_trigger,
+ .open = fsl_asrc_dma_startup,
+ .close = fsl_asrc_dma_shutdown,
+ .pointer = fsl_asrc_dma_pcm_pointer,
+};
+
+static int fsl_asrc_dma_pcm_new(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm *pcm = rtd->pcm;
+ u64 dma_mask = DMA_BIT_MASK(32);
+ int ret, i;
+
+ if (!card->dev->dma_mask)
+ card->dev->dma_mask = &dma_mask;
+ if (!card->dev->coherent_dma_mask)
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+ for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_LAST; i++) {
+ substream = pcm->streams[i].substream;
+
+ ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
+ FSL_ASRC_DMABUF_SIZE, &substream->dma_buffer);
+ if (ret) {
+ dev_err(card->dev, "failed to allocate DMA buffer\n");
+ goto err;
+ }
+ }
+
+ return 0;
+
+err:
+ if (--i == 0)
+ snd_dma_free_pages(&pcm->streams[i].substream->dma_buffer);
+
+ return ret;
+}
+
+static void fsl_asrc_dma_pcm_free(struct snd_pcm *pcm)
+{
+ struct snd_pcm_substream *substream;
+ int i;
+
+ for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_LAST; i++) {
+ substream = pcm->streams[i].substream;
+ if (!substream)
+ continue;
+
+ snd_dma_free_pages(&substream->dma_buffer);
+ substream->dma_buffer.area = NULL;
+ substream->dma_buffer.addr = 0;
+ }
+}
+
+struct snd_soc_platform_driver fsl_asrc_platform = {
+ .ops = &fsl_asrc_dma_pcm_ops,
+ .pcm_new = fsl_asrc_dma_pcm_new,
+ .pcm_free = fsl_asrc_dma_pcm_free,
+};
+EXPORT_SYMBOL_GPL(fsl_asrc_platform);
--
1.8.4
^ permalink raw reply related
* Re: kmemleak: Unable to handle kernel paging request
From: Denis Kirjanov @ 2014-06-13 10:26 UTC (permalink / raw)
To: Catalin Marinas
Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org, Paul Mackerras,
Naoya Horiguchi, linuxppc-dev
In-Reply-To: <20140613085640.GA21018@arm.com>
On 6/13/14, Catalin Marinas <catalin.marinas@arm.com> wrote:
> On Fri, Jun 13, 2014 at 08:12:08AM +0100, Denis Kirjanov wrote:
>> On 6/12/14, Catalin Marinas <catalin.marinas@arm.com> wrote:
>> > On Thu, Jun 12, 2014 at 01:00:57PM +0100, Denis Kirjanov wrote:
>> >> On 6/12/14, Denis Kirjanov <kda@linux-powerpc.org> wrote:
>> >> > On 6/12/14, Catalin Marinas <catalin.marinas@arm.com> wrote:
>> >> >> On 11 Jun 2014, at 21:04, Denis Kirjanov <kda@linux-powerpc.org>
>> >> >> wrote:
>> >> >>> On 6/11/14, Catalin Marinas <catalin.marinas@arm.com> wrote:
>> >> >>>> On Wed, Jun 11, 2014 at 04:13:07PM +0400, Denis Kirjanov wrote:
>> >> >>>>> I got a trace while running 3.15.0-08556-gdfb9454:
>> >> >>>>>
>> >> >>>>> [ 104.534026] Unable to handle kernel paging request for data
>> >> >>>>> at
>> >> >>>>> address 0xc00000007f000000
>> >> >>>>
>> >> >>>> Were there any kmemleak messages prior to this, like "kmemleak
>> >> >>>> disabled"? There could be a race when kmemleak is disabled
>> >> >>>> because
>> >> >>>> of
>> >> >>>> some fatal (for kmemleak) error while the scanning is taking
>> >> >>>> place
>> >> >>>> (which needs some more thinking to fix properly).
>> >> >>>
>> >> >>> No. I checked for the similar problem and didn't find anything
>> >> >>> relevant.
>> >> >>> I'll try to bisect it.
>> >> >>
>> >> >> Does this happen soon after boot? I guess it=E2=80=99s the first s=
can
>> >> >> (scheduled at around 1min after boot). Something seems to be
>> >> >> telling
>> >> >> kmemleak that there is a valid memory block at 0xc00000007f000000.
>> >> >
>> >> > Yeah, it happens after a while with a booted system so that's the
>> >> > first kmemleak scan.
>> >>
>> >> I've bisected to this commit: d4c54919ed86302094c0ca7d48a8cbd4ee753e9=
2
>> >> "mm: add !pte_present() check on existing hugetlb_entry callbacks".
>> >> Reverting the commit fixes the issue
>> >
>> > I can't figure how this causes the problem but I have more questions.
>> > Is
>> > 0xc00000007f000000 address always the same in all crashes? If yes, you
>> > could comment out start_scan_thread() in kmemleak_late_init() to avoid
>> > the scanning thread starting. Once booted, you can run:
>> >
>> > echo dump=3D0xc00000007f000000 > /sys/kernel/debug/kmemleak
>> >
>> > and check the dmesg for what kmemleak knows about that address, when i=
t
>> > was allocated and whether it should be mapped or not.
>>
>> The address is always the same.
>>
>> [ 179.466239] kmemleak: Object 0xc00000007f000000 (size 16777216):
>> [ 179.466503] kmemleak: comm "swapper/0", pid 0, jiffies 4294892300
>> [ 179.466508] kmemleak: min_count =3D 0
>> [ 179.466512] kmemleak: count =3D 0
>> [ 179.466517] kmemleak: flags =3D 0x1
>> [ 179.466522] kmemleak: checksum =3D 0
>> [ 179.466526] kmemleak: backtrace:
>> [ 179.466531] [<c000000000afc3dc>]
>> .memblock_alloc_range_nid+0x68/0x88
>> [ 179.466544] [<c000000000afc444>] .memblock_alloc_base+0x20/0x58
>> [ 179.466553] [<c000000000ae96cc>] .alloc_dart_table+0x5c/0xb0
>> [ 179.466561] [<c000000000aea300>] .pmac_probe+0x38/0xa0
>> [ 179.466569] [<000000000002166c>] 0x2166c
>> [ 179.466579] [<0000000000ae0e68>] 0xae0e68
>> [ 179.466587] [<0000000000009bc4>] 0x9bc4
>
> OK, so that's the DART table allocated via alloc_dart_table(). Is
> dart_tablebase removed from the kernel linear mapping after allocation?
> If that's the case, we need to tell kmemleak to ignore this block (see
> patch below, untested). But I still can't explain how commit
> d4c54919ed863020 causes this issue.
>
> (also cc'ing the powerpc list and maintainers)
Ok, your path fixes the oops.
Ben, can you shed some light on this issue?
Thanks!
> ---------------8<--------------------------
>
> From 09a7f1c97166c7bdca7ca4e8a4ff2774f3706ea3 Mon Sep 17 00:00:00 2001
> From: Catalin Marinas <catalin.marinas@arm.com>
> Date: Fri, 13 Jun 2014 09:44:21 +0100
> Subject: [PATCH] powerpc/kmemleak: Do not scan the DART table
>
> The DART table allocation is registered to kmemleak via the
> memblock_alloc_base() call. However, the DART table is later unmapped
> and dart_tablebase VA no longer accessible. This patch tells kmemleak
> not to scan this block and avoid an unhandled paging request.
>
> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Paul Mackerras <paulus@samba.org>
> ---
> arch/powerpc/sysdev/dart_iommu.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/arch/powerpc/sysdev/dart_iommu.c
> b/arch/powerpc/sysdev/dart_iommu.c
> index 62c47bb76517..9e5353ff6d1b 100644
> --- a/arch/powerpc/sysdev/dart_iommu.c
> +++ b/arch/powerpc/sysdev/dart_iommu.c
> @@ -476,6 +476,11 @@ void __init alloc_dart_table(void)
> */
> dart_tablebase =3D (unsigned long)
> __va(memblock_alloc_base(1UL<<24, 1UL<<24, 0x80000000L));
> + /*
> + * The DART space is later unmapped from the kernel linear mapping and
> + * accessing dart_tablebase during kmemleak scanning will fault.
> + */
> + kmemleak_no_scan((void *)dart_tablebase);
>
> printk(KERN_INFO "DART table allocated at: %lx\n", dart_tablebase);
> }
>
^ permalink raw reply
* Re: Device Tree Binding for DSA on P1023RDB
From: Pannirselvam Kanagaratnam @ 2014-06-13 10:34 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <1402608088.6603.549.camel@snotra.buserror.net>
On Fri, Jun 13, 2014, at 05:21 AM, Scott Wood wrote:
> On Thu, 2014-06-12 at 23:36 +0800, Pannirselvam Kanagaratnam wrote:
> > The QORIQ P1023RDB has an option to populate the Marvell 88E6165
> > Ethernet switch. We populated this device and was able to initialize
> > it as a basic switch in U-Boot. However, the switch driver was not
> > loaded upon kernel bootup. DSA kernel config was enabled for the
> > 88E6165. The following patch was applied:
> >
> >
> > http://patchwork.ozlabs.org/patch/230257/
> >
> >
> > The switch is attached to phy address 0x3 via dtsec2. My dts file is
> > as below. Would appreciate any feedback on whether the DSA is
> > correctly structured in the dts.
>
> If you have a dtsec driver you're not working with an upstream kernel
> (or you've ported a lot of SDK code to it)... What tree are you working
> with? Are there prerequisites to the above patch that you might be
> missing?
>
I am using QorIQ-SDK-V1.5-20131219-yocto (3.8-r11.1). Not sure if I am
missing
any prerequisites.
> The above patch is a platform driver and you put the node in the
> toplevel device tree node. Have you added marvell,dsa to the list of
> compatible strings that get probed (of_device_ids in corenet_generic.c
> or an equivalent list in your SDK kernel)?
> >
I was missing this. I added it in arch/powerpc/platforms/85xx/common.c
After adding the above, the driver is now attempting to probe. However,
I got the following message:
Distributed Switch Architecture driver version 0.1
dsa: probe of dsa.16 failed with error -22
I dumped the mdio, mdio_bus and ethernet parameters:
1) For mdio = of_parse_phandle(np, "dsa,mii-bus", 0); I get the
following:
np-name: dsa
mdio-name: mdio
mdio-type: <NULL>
mdio-full-name: /soc@ff600000/fman@100000/mdio@e1120
2) mdio_bus = of_mdio_find_bus(mdio);
mdio_bus_name: Freescale PowerQUICC MII Bus
mdio_bus_id: mdio@ff7e1120
3) ethernet = of_parse_phandle(np, "dsa,ethernet", 0);
ethernet-name: ethernet
ethernet-type: <NULL>
ethernet-full-name: /soc@ff600000/fman@100000/ethernet@e2000
Anything amiss here?
> > dsa@0 {
> > compatible = "marvell,dsa";
> > #address-cells = <2>;
> > #size-cells = <0>;
> >
> > interrupts = <3>;
>
> This interrupts property needs to be four cells rather than one, if MPIC
> is the parent -- assuming you have #interrupt-cells = <4> and not some
> old device tree with #interrupt-cells = <2>, but in any case you need
> more than one cell.
>
The interrupt is an optional entry and not supported by the driver. I
have omitted it for now.
Pannir
^ 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