* Re: [PATCH 08/11] [POWERPC] qe_lib: implement QE GTM support
From: Scott Wood @ 2008-02-04 20:30 UTC (permalink / raw)
To: Anton Vorontsov; +Cc: linuxppc-dev
In-Reply-To: <20080203171019.GH28024@localhost.localdomain>
On Sun, Feb 03, 2008 at 08:10:19PM +0300, Anton Vorontsov wrote:
> GTM stands for General-purpose Timers Module and able to generate
> timer{1,2,3,4} interrupts.
>
> There are several limitations in this support:
> 1. Cascaded (32 bit) timers unimplemented (1-2, 3-4).
> This is straightforward to implement when needed, two timers should
> be marked as "requested" and configured as appropriate.
> 2. Super-cascaded (64 bit) timers unimplemented (1-2-3-4).
> This is also straightforward to implement when needed, all timers
> should be marked as "requested" and configured as appropriate.
This isn't QE-specific; the same (as far as I see) timer hardware exists on,
for example, mpc8313 and mpc8349.
> +config QE_GTM
> + bool
> + help
> + QE General-Purpose Timers Module support
No bool text?
> +struct gtm_timer {
> + unsigned int irq;
> + bool requested;
> +
> + u8 __iomem *gtcfr;
> + u16 __iomem *gtmdr;
> + u16 __iomem *gtpsr;
> + u16 __iomem *gtcnr;
> + u16 __iomem *gtrfr;
> + u16 __iomem *gtevr;
> +};
__be16
> +static struct gtm_timer timers[4];
> +static struct qe_timers __iomem *qet;
> +static spinlock_t gtm_lock = __SPIN_LOCK_UNLOCKED(gtm_lock);
static DEFINE_SPINLOCK(gtm_lock);
Put these in a struct so multiple timer blocks can be supported (the non-QE
chips tend to have two blocks).
> +int qe_reset_ref_timer_16(int num, unsigned int hz, u16 ref)
What does this function do? What goes in "hz" and "ref"? Is it periodic or
one-shot?
-Scott
^ permalink raw reply
* Re: [RFC][PATCH] PowerPC: 4xx PCIe indirect DCR spinlock fix.
From: Benjamin Herrenschmidt @ 2008-02-04 20:50 UTC (permalink / raw)
To: Valentine Barshak; +Cc: linuxppc-dev
In-Reply-To: <20080204182740.GA2898@ru.mvista.com>
On Mon, 2008-02-04 at 21:27 +0300, Valentine Barshak wrote:
> Since we have mfdcri() and mtdcri() as macros, we can't use constructions, such
> as "mtdcri(base, reg, mfdcri(base, reg) | val)". In this case the mfdcri() stuff
> is not evaluated first. It's evaluated inside the mtdcr() macro and we have
> the dcr_ind_lock spinlock acquired twice. To avoid this error, I've added
> set_dcri() and clr_dcri() macros which set/clear the specified bits.
>
> Signed-off-by: Valentine Barshak <vbarshak@ru.mvista.com>
No, better is to fix the macros to use functions.
Make mfdcri/mtdcri call into __mfdcri/__mtdcri functions after fixing
up the macro register names, and have those be inlines that take the
lock.
Ben.
> arch/powerpc/sysdev/ppc4xx_pci.c | 13 +++++--------
> include/asm-powerpc/dcr-native.h | 22 ++++++++++++++++++++++
> 2 files changed, 27 insertions(+), 8 deletions(-)
>
> diff -pruN linux-2.6.orig/arch/powerpc/sysdev/ppc4xx_pci.c linux-2.6/arch/powerpc/sysdev/ppc4xx_pci.c
> --- linux-2.6.orig/arch/powerpc/sysdev/ppc4xx_pci.c 2008-02-04 20:05:37.000000000 +0300
> +++ linux-2.6/arch/powerpc/sysdev/ppc4xx_pci.c 2008-02-04 20:16:33.000000000 +0300
> @@ -645,7 +645,7 @@ static int __init ppc440spe_pciex_core_i
> int time_out = 20;
>
> /* Set PLL clock receiver to LVPECL */
> - mtdcri(SDR0, PESDR0_PLLLCT1, mfdcri(SDR0, PESDR0_PLLLCT1) | 1 << 28);
> + set_dcri(SDR0, PESDR0_PLLLCT1, 1 << 28);
>
> /* Shouldn't we do all the calibration stuff etc... here ? */
> if (ppc440spe_pciex_check_reset(np))
> @@ -659,8 +659,7 @@ static int __init ppc440spe_pciex_core_i
> }
>
> /* De-assert reset of PCIe PLL, wait for lock */
> - mtdcri(SDR0, PESDR0_PLLLCT1,
> - mfdcri(SDR0, PESDR0_PLLLCT1) & ~(1 << 24));
> + clr_dcri(SDR0, PESDR0_PLLLCT1, 1 << 24);
> udelay(3);
>
> while (time_out) {
> @@ -712,9 +711,8 @@ static int ppc440spe_pciex_init_port_hw(
> mtdcri(SDR0, port->sdr_base + PESDRn_440SPE_HSSL7SET1,
> 0x35000000);
> }
> - val = mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET);
> - mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET,
> - (val & ~(1 << 24 | 1 << 16)) | 1 << 12);
> + clr_dcri(SDR0, port->sdr_base + PESDRn_RCSSET, 1 << 24 | 1 << 16)
> + set_dcri(SDR0, port->sdr_base + PESDRn_RCSSET, 1 << 12);
>
> return 0;
> }
> @@ -1042,8 +1040,7 @@ static int __init ppc4xx_pciex_port_init
> port->link = 0;
> }
>
> - mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET,
> - mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET) | 1 << 20);
> + set_dcri(SDR0, port->sdr_base + PESDRn_RCSSET, 1 << 20);
> msleep(100);
>
> return 0;
> diff -pruN linux-2.6.orig/include/asm-powerpc/dcr-native.h linux-2.6/include/asm-powerpc/dcr-native.h
> --- linux-2.6.orig/include/asm-powerpc/dcr-native.h 2008-02-04 20:06:34.000000000 +0300
> +++ linux-2.6/include/asm-powerpc/dcr-native.h 2008-02-04 20:16:33.000000000 +0300
> @@ -79,6 +79,28 @@ do { \
> spin_unlock_irqrestore(&dcr_ind_lock, flags); \
> } while (0)
>
> +#define set_dcri(base, reg, data) \
> +do { \
> + unsigned long flags; \
> + unsigned int val; \
> + spin_lock_irqsave(&dcr_ind_lock, flags); \
> + mtdcr(DCRN_ ## base ## _CONFIG_ADDR, reg); \
> + val = mfdcr(DCRN_ ## base ## _CONFIG_DATA); \
> + mtdcr(DCRN_ ## base ## _CONFIG_DATA, val | (data)); \
> + spin_unlock_irqrestore(&dcr_ind_lock, flags); \
> +} while (0)
> +
> +#define clr_dcri(base, reg, data) \
> +do { \
> + unsigned long flags; \
> + unsigned int val; \
> + spin_lock_irqsave(&dcr_ind_lock, flags); \
> + mtdcr(DCRN_ ## base ## _CONFIG_ADDR, reg); \
> + val = mfdcr(DCRN_ ## base ## _CONFIG_DATA); \
> + mtdcr(DCRN_ ## base ## _CONFIG_DATA, val & ~(data)); \
> + spin_unlock_irqrestore(&dcr_ind_lock, flags); \
> +} while (0)
> +
> #endif /* __ASSEMBLY__ */
> #endif /* __KERNEL__ */
> #endif /* _ASM_POWERPC_DCR_NATIVE_H */
^ permalink raw reply
* Re: [PATCH 08/11] [POWERPC] qe_lib: implement QE GTM support
From: Anton Vorontsov @ 2008-02-04 20:56 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <20080204203003.GA4202@loki.buserror.net>
On Mon, Feb 04, 2008 at 02:30:04PM -0600, Scott Wood wrote:
> On Sun, Feb 03, 2008 at 08:10:19PM +0300, Anton Vorontsov wrote:
> > GTM stands for General-purpose Timers Module and able to generate
> > timer{1,2,3,4} interrupts.
> >
> > There are several limitations in this support:
> > 1. Cascaded (32 bit) timers unimplemented (1-2, 3-4).
> > This is straightforward to implement when needed, two timers should
> > be marked as "requested" and configured as appropriate.
> > 2. Super-cascaded (64 bit) timers unimplemented (1-2-3-4).
> > This is also straightforward to implement when needed, all timers
> > should be marked as "requested" and configured as appropriate.
>
> This isn't QE-specific; the same (as far as I see) timer hardware exists on,
> for example, mpc8313 and mpc8349.
In my endless todo list. I'll try to evolve it to support fsl gtms in
general. Though the problem is that, for example, for QE USB we prefer
QE timers. So, we probably want to pass timers via device tree to
distinguish them.
> > +config QE_GTM
> > + bool
> > + help
> > + QE General-Purpose Timers Module support
>
> No bool text?
No. This is silent config option.
> > +struct gtm_timer {
> > + unsigned int irq;
> > + bool requested;
> > +
> > + u8 __iomem *gtcfr;
> > + u16 __iomem *gtmdr;
> > + u16 __iomem *gtpsr;
> > + u16 __iomem *gtcnr;
> > + u16 __iomem *gtrfr;
> > + u16 __iomem *gtevr;
> > +};
>
> __be16
Will do.
> > +static struct gtm_timer timers[4];
> > +static struct qe_timers __iomem *qet;
> > +static spinlock_t gtm_lock = __SPIN_LOCK_UNLOCKED(gtm_lock);
>
> static DEFINE_SPINLOCK(gtm_lock);
I'm trying to open-code as much as I could (well, not as much, but
just using common sense :-), so I prefer the first variant, if you
don't mind. DEFINE_SPINLOCK() and above are equivalents.
This is not something I'm going to argue about, though. Just ask
one more time and I'll simply change it to DEFINE_SPINLOCK().
> Put these in a struct so multiple timer blocks can be supported (the non-QE
> chips tend to have two blocks).
Yes, this is in my todo list. Btw, QE chips have three gtms, QE + 2 IMMR.
> > +int qe_reset_ref_timer_16(int num, unsigned int hz, u16 ref)
>
> What does this function do? What goes in "hz" and "ref"? Is it periodic or
> one-shot?
"ref" means that it counts to some reference value and fires the
interrupt. Hz is count rate. This particular function implements
"reset reference mode", timer will reset itself when reference
value is reached. We probably want to add frr flag (free run).
Will kernel-doc this function.
--
Anton Vorontsov
email: cbou@mail.ru
backup email: ya-cbou@yandex.ru
irc://irc.freenode.net/bd2
^ permalink raw reply
* Re: compile quirk linux-2.6.24 (with workaround)
From: Josh Boyer @ 2008-02-04 21:01 UTC (permalink / raw)
To: Bernhard Reiter; +Cc: linuxppc-dev, debian-powerpc, paulus
In-Reply-To: <200802031729.12069.bernhard@intevation.de>
On Sun, 3 Feb 2008 17:29:05 +0100
Bernhard Reiter <bernhard@intevation.de> wrote:
> Dear linux powerpc Maintainers and Users,
>
> recently I have tried to compile a new kernel on a Debian sarge ppc
> system (PowerBook5,6 MacRISC3 Power Macintosh).
>
> The build system bailed out with
> BOOTCC arch/powerpc/boot/4xx.o
> cc1: error: bad value (440) for -mcpu= switch
> make[1]: *** [arch/powerpc/boot/4xx.o] Fehler 1
>
> I have tracked this a few steps and the attached patch made the compile for me
> as my compiler gcc-Version 3.3.5 (Debian 1:3.3.5-13)
> cannot produce code for 4xx it seems.
>
> The "ARCH=ppc64" I have came about also looked wrong, but I do not know
> if this part of the patch is really necessary.
> It is just a workaround, as I have no insight of what is really going wrong.
That patch really won't fly. I'll try go come up with something a bit
more robust when I can.
josh
^ permalink raw reply
* Re: Commit for mm/page_alloc.c breaks boot process on my machine
From: Gerhard Pircher @ 2008-02-04 22:20 UTC (permalink / raw)
To: Mel Gorman; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <20080204104232.GB29484@csn.ul.ie>
-------- Original-Nachricht --------
> Datum: Mon, 4 Feb 2008 10:42:32 +0000
> Von: Mel Gorman <mel@csn.ul.ie>
> An: Gerhard Pircher <gerhard_pircher@gmx.net>
> CC: linux-kernel@vger.kernel.org, linuxppc-dev@ozlabs.org
> Betreff: Re: Commit for mm/page_alloc.c breaks boot process on my machine
> > > > > 2. Any chance of seeing a dmesg log?
> > > > That's a little bit of a problem. The kernel log in memory doesn't
> > > > show any kernel oops, but is also fragmented (small fragments seem
> > > > to have been overwritten with 0x0).
> > >
> > > err, that doesn't sound very healthy.
> >
> > Yeah, I know. But the platform code hasn't changed much when porting it
> > from arch/ppc to arch/powerpc. That's why I'm a little bit lost in this
> > case. :-)
> >
>
> I'm at a bit of a loss to guess what might have changed in powerpc code
> that would explain this. I've added the linuxppc-dev mailing list in
> case they can make a guess.
Yes, I'll try to get some comments on the linuxppc-dev mailing list.
> I think you are also going to need to start bisecting searching
> specifically for the patch that causes these overwrites.
I think I had a similar problem with kernel v2.6.23, too and therefore
waited for kernel 2.6.24. So the problem may exist since a long time.
> It's a virtual address so it depends on the value of CONFIG_KERNEL_START
> as to whether this is a user program address or not.
AFAIK start_kernel() is called very early in the boot process, were no
user or kernel thread is active. I also wonder why the kernel crashes when
the mem boot option is used. Let's see what the linuxppc-dev people say.
Thanks for your help!
Gerhard
--
Psssst! Schon vom neuen GMX MultiMessenger gehört?
Der kann`s mit allen: http://www.gmx.net/de/go/multimessenger
^ permalink raw reply
* Re: [PATCH 1/1] [PPC] 8xx swap bug-fix
From: Vitaly Bordug @ 2008-02-04 22:38 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev, Paul, Mackerras
In-Reply-To: <20080204182421.GA3930@loki.buserror.net>
On Mon, 4 Feb 2008 12:24:21 -0600
Scott Wood wrote:
> On Sat, Feb 02, 2008 at 12:22:17PM +0100, Jochen Friedrich wrote:
> > Hi Yuri,
> >
> > > Here is the patch which makes Linux-2.6 swap routines operate
> > > correctly on the ppc-8xx-based machines.
> >
> > is there any 8xx board left which isn't ported to ARCH=powerpc?
>
> More importantly, is this something that is also broken in
> arch/powerpc? It looks like it has the same code...
>
yes, it is. Though there is currently no best-at-all solution, this looks worth trying.
I'll have a look how the 8xx feels under load and report back.
--
Sincerely, Vitaly
^ permalink raw reply
* Re: 2.6.24-mm1: ppc32: too few arguments to function 'reserve_bootmem'
From: Andrew Morton @ 2008-02-04 22:40 UTC (permalink / raw)
To: Mariusz Kozlowski; +Cc: linuxppc-dev, bwalle, paulus, linux-kernel
In-Reply-To: <200802042129.03065.m.kozlowski@tuxland.pl>
On Mon, 4 Feb 2008 21:29:02 +0100
Mariusz Kozlowski <m.kozlowski@tuxland.pl> wrote:
> Hello,
>
> This is from ppc32:
>
> CC arch/powerpc/mm/mem.o
> arch/powerpc/mm/mem.c: In function 'do_init_bootmem':
> arch/powerpc/mm/mem.c:256: error: too few arguments to function 'reserve_bootmem'
> arch/powerpc/mm/mem.c:261: error: too few arguments to function 'reserve_bootmem'
>
> Leftover from introduce-flags-for-reserve_bootmem.patch?
>
Yes, I've had to fix that patch many times.
--- a/arch/powerpc/mm/mem.c~introduce-flags-for-reserve_bootmem-powerpc-fix
+++ a/arch/powerpc/mm/mem.c
@@ -253,12 +253,13 @@ void __init do_init_bootmem(void)
lmb_size_bytes(&lmb.reserved, i) - 1;
if (addr < total_lowmem)
reserve_bootmem(lmb.reserved.region[i].base,
- lmb_size_bytes(&lmb.reserved, i));
+ lmb_size_bytes(&lmb.reserved, i),
+ BOOTMEM_DEFAULT);
else if (lmb.reserved.region[i].base < total_lowmem) {
unsigned long adjusted_size = total_lowmem -
lmb.reserved.region[i].base;
reserve_bootmem(lmb.reserved.region[i].base,
- adjusted_size);
+ adjusted_size, BOOTMEM_DWEFAULT);
}
}
#else
_
We did this wrong. We should have introduced a new reserve_bootmem_foo()
and migrated over to that in stages. Once all callers are migrated, remove
the old interface.
^ permalink raw reply
* [PATCH] Made FSL Book-E PMC support more generic
From: Andy Fleming @ 2008-02-04 23:13 UTC (permalink / raw)
To: linuxppc-dev, galak
Some of the more recent e300 cores have the same performance monitor
implementation as the e500. e300 isn't book-e, so the name isn't
really appropriate. In preparation for e300 support, rename a bunch
of fsl_booke things to say fsl_emb (Freescale Embedded Performance Monitors).
Signed-off-by: Andy Fleming <afleming@freescale.com>
---
arch/powerpc/Kconfig | 3 +
arch/powerpc/kernel/cputable.c | 4 +-
arch/powerpc/kernel/pmc.c | 2 +-
arch/powerpc/oprofile/Makefile | 2 +-
arch/powerpc/oprofile/common.c | 6 +-
arch/powerpc/oprofile/op_model_fsl_booke.c | 371 ----------------------------
arch/powerpc/oprofile/op_model_fsl_emb.c | 369 +++++++++++++++++++++++++++
arch/powerpc/platforms/Kconfig.cputype | 1 +
include/asm-powerpc/cputable.h | 2 +-
include/asm-powerpc/oprofile_impl.h | 2 +-
include/asm-powerpc/reg.h | 4 +
include/asm-powerpc/reg_booke.h | 62 -----
include/asm-powerpc/reg_fsl_emb.h | 72 ++++++
13 files changed, 458 insertions(+), 442 deletions(-)
delete mode 100644 arch/powerpc/oprofile/op_model_fsl_booke.c
create mode 100644 arch/powerpc/oprofile/op_model_fsl_emb.c
create mode 100644 include/asm-powerpc/reg_fsl_emb.h
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 5e10838..079c0e3 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -473,6 +473,9 @@ config FSL_PCI
bool
select PPC_INDIRECT_PCI
+config FSL_EMB_PERFMON
+ bool
+
# Yes MCA RS/6000s exist but Linux-PPC does not currently support any
config MCA
bool
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 14c3b07..c8af497 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -1441,7 +1441,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.dcache_bsize = 32,
.num_pmcs = 4,
.oprofile_cpu_type = "ppc/e500",
- .oprofile_type = PPC_OPROFILE_BOOKE,
+ .oprofile_type = PPC_OPROFILE_FSL_EMB,
.machine_check = machine_check_e500,
.platform = "ppc8540",
},
@@ -1459,7 +1459,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.dcache_bsize = 32,
.num_pmcs = 4,
.oprofile_cpu_type = "ppc/e500",
- .oprofile_type = PPC_OPROFILE_BOOKE,
+ .oprofile_type = PPC_OPROFILE_FSL_EMB,
.machine_check = machine_check_e500,
.platform = "ppc8548",
},
diff --git a/arch/powerpc/kernel/pmc.c b/arch/powerpc/kernel/pmc.c
index ea04e0a..0516e2d 100644
--- a/arch/powerpc/kernel/pmc.c
+++ b/arch/powerpc/kernel/pmc.c
@@ -26,7 +26,7 @@
static void dummy_perf(struct pt_regs *regs)
{
-#if defined(CONFIG_FSL_BOOKE) && !defined(CONFIG_E200)
+#if defined(CONFIG_FSL_EMB_PERFMON)
mtpmr(PMRN_PMGC0, mfpmr(PMRN_PMGC0) & ~PMGC0_PMIE);
#elif defined(CONFIG_PPC64) || defined(CONFIG_6xx)
if (cur_cpu_spec->pmc_type == PPC_PMC_IBM)
diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile
index c5f64c3..2ef6b0d 100644
--- a/arch/powerpc/oprofile/Makefile
+++ b/arch/powerpc/oprofile/Makefile
@@ -15,5 +15,5 @@ oprofile-$(CONFIG_OPROFILE_CELL) += op_model_cell.o \
cell/spu_profiler.o cell/vma_map.o \
cell/spu_task_sync.o
oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o op_model_pa6t.o
-oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o
+oprofile-$(CONFIG_FSL_EMB_PERFMON) += op_model_fsl_emb.o
oprofile-$(CONFIG_6xx) += op_model_7450.o
diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c
index a28cce1..4908dc9 100644
--- a/arch/powerpc/oprofile/common.c
+++ b/arch/powerpc/oprofile/common.c
@@ -202,9 +202,9 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
model = &op_model_7450;
break;
#endif
-#ifdef CONFIG_FSL_BOOKE
- case PPC_OPROFILE_BOOKE:
- model = &op_model_fsl_booke;
+#if defined(CONFIG_FSL_EMB_PERFMON)
+ case PPC_OPROFILE_FSL_EMB:
+ model = &op_model_fsl_emb;
break;
#endif
default:
diff --git a/arch/powerpc/oprofile/op_model_fsl_booke.c b/arch/powerpc/oprofile/op_model_fsl_booke.c
deleted file mode 100644
index 183a28b..0000000
--- a/arch/powerpc/oprofile/op_model_fsl_booke.c
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * arch/powerpc/oprofile/op_model_fsl_booke.c
- *
- * Freescale Book-E oprofile support, based on ppc64 oprofile support
- * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
- *
- * Copyright (c) 2004 Freescale Semiconductor, Inc
- *
- * Author: Andy Fleming
- * Maintainer: Kumar Gala <galak@kernel.crashing.org>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/oprofile.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-#include <asm/ptrace.h>
-#include <asm/system.h>
-#include <asm/processor.h>
-#include <asm/cputable.h>
-#include <asm/reg_booke.h>
-#include <asm/page.h>
-#include <asm/pmc.h>
-#include <asm/oprofile_impl.h>
-
-static unsigned long reset_value[OP_MAX_COUNTER];
-
-static int num_counters;
-static int oprofile_running;
-
-static inline u32 get_pmlca(int ctr)
-{
- u32 pmlca;
-
- switch (ctr) {
- case 0:
- pmlca = mfpmr(PMRN_PMLCA0);
- break;
- case 1:
- pmlca = mfpmr(PMRN_PMLCA1);
- break;
- case 2:
- pmlca = mfpmr(PMRN_PMLCA2);
- break;
- case 3:
- pmlca = mfpmr(PMRN_PMLCA3);
- break;
- default:
- panic("Bad ctr number\n");
- }
-
- return pmlca;
-}
-
-static inline void set_pmlca(int ctr, u32 pmlca)
-{
- switch (ctr) {
- case 0:
- mtpmr(PMRN_PMLCA0, pmlca);
- break;
- case 1:
- mtpmr(PMRN_PMLCA1, pmlca);
- break;
- case 2:
- mtpmr(PMRN_PMLCA2, pmlca);
- break;
- case 3:
- mtpmr(PMRN_PMLCA3, pmlca);
- break;
- default:
- panic("Bad ctr number\n");
- }
-}
-
-static inline unsigned int ctr_read(unsigned int i)
-{
- switch(i) {
- case 0:
- return mfpmr(PMRN_PMC0);
- case 1:
- return mfpmr(PMRN_PMC1);
- case 2:
- return mfpmr(PMRN_PMC2);
- case 3:
- return mfpmr(PMRN_PMC3);
- default:
- return 0;
- }
-}
-
-static inline void ctr_write(unsigned int i, unsigned int val)
-{
- switch(i) {
- case 0:
- mtpmr(PMRN_PMC0, val);
- break;
- case 1:
- mtpmr(PMRN_PMC1, val);
- break;
- case 2:
- mtpmr(PMRN_PMC2, val);
- break;
- case 3:
- mtpmr(PMRN_PMC3, val);
- break;
- default:
- break;
- }
-}
-
-
-static void init_pmc_stop(int ctr)
-{
- u32 pmlca = (PMLCA_FC | PMLCA_FCS | PMLCA_FCU |
- PMLCA_FCM1 | PMLCA_FCM0);
- u32 pmlcb = 0;
-
- switch (ctr) {
- case 0:
- mtpmr(PMRN_PMLCA0, pmlca);
- mtpmr(PMRN_PMLCB0, pmlcb);
- break;
- case 1:
- mtpmr(PMRN_PMLCA1, pmlca);
- mtpmr(PMRN_PMLCB1, pmlcb);
- break;
- case 2:
- mtpmr(PMRN_PMLCA2, pmlca);
- mtpmr(PMRN_PMLCB2, pmlcb);
- break;
- case 3:
- mtpmr(PMRN_PMLCA3, pmlca);
- mtpmr(PMRN_PMLCB3, pmlcb);
- break;
- default:
- panic("Bad ctr number!\n");
- }
-}
-
-static void set_pmc_event(int ctr, int event)
-{
- u32 pmlca;
-
- pmlca = get_pmlca(ctr);
-
- pmlca = (pmlca & ~PMLCA_EVENT_MASK) |
- ((event << PMLCA_EVENT_SHIFT) &
- PMLCA_EVENT_MASK);
-
- set_pmlca(ctr, pmlca);
-}
-
-static void set_pmc_user_kernel(int ctr, int user, int kernel)
-{
- u32 pmlca;
-
- pmlca = get_pmlca(ctr);
-
- if(user)
- pmlca &= ~PMLCA_FCU;
- else
- pmlca |= PMLCA_FCU;
-
- if(kernel)
- pmlca &= ~PMLCA_FCS;
- else
- pmlca |= PMLCA_FCS;
-
- set_pmlca(ctr, pmlca);
-}
-
-static void set_pmc_marked(int ctr, int mark0, int mark1)
-{
- u32 pmlca = get_pmlca(ctr);
-
- if(mark0)
- pmlca &= ~PMLCA_FCM0;
- else
- pmlca |= PMLCA_FCM0;
-
- if(mark1)
- pmlca &= ~PMLCA_FCM1;
- else
- pmlca |= PMLCA_FCM1;
-
- set_pmlca(ctr, pmlca);
-}
-
-static void pmc_start_ctr(int ctr, int enable)
-{
- u32 pmlca = get_pmlca(ctr);
-
- pmlca &= ~PMLCA_FC;
-
- if (enable)
- pmlca |= PMLCA_CE;
- else
- pmlca &= ~PMLCA_CE;
-
- set_pmlca(ctr, pmlca);
-}
-
-static void pmc_start_ctrs(int enable)
-{
- u32 pmgc0 = mfpmr(PMRN_PMGC0);
-
- pmgc0 &= ~PMGC0_FAC;
- pmgc0 |= PMGC0_FCECE;
-
- if (enable)
- pmgc0 |= PMGC0_PMIE;
- else
- pmgc0 &= ~PMGC0_PMIE;
-
- mtpmr(PMRN_PMGC0, pmgc0);
-}
-
-static void pmc_stop_ctrs(void)
-{
- u32 pmgc0 = mfpmr(PMRN_PMGC0);
-
- pmgc0 |= PMGC0_FAC;
-
- pmgc0 &= ~(PMGC0_PMIE | PMGC0_FCECE);
-
- mtpmr(PMRN_PMGC0, pmgc0);
-}
-
-static void dump_pmcs(void)
-{
- printk("pmgc0: %x\n", mfpmr(PMRN_PMGC0));
- printk("pmc\t\tpmlca\t\tpmlcb\n");
- printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC0),
- mfpmr(PMRN_PMLCA0), mfpmr(PMRN_PMLCB0));
- printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC1),
- mfpmr(PMRN_PMLCA1), mfpmr(PMRN_PMLCB1));
- printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC2),
- mfpmr(PMRN_PMLCA2), mfpmr(PMRN_PMLCB2));
- printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC3),
- mfpmr(PMRN_PMLCA3), mfpmr(PMRN_PMLCB3));
-}
-
-static int fsl_booke_cpu_setup(struct op_counter_config *ctr)
-{
- int i;
-
- /* freeze all counters */
- pmc_stop_ctrs();
-
- for (i = 0;i < num_counters;i++) {
- init_pmc_stop(i);
-
- set_pmc_event(i, ctr[i].event);
-
- set_pmc_user_kernel(i, ctr[i].user, ctr[i].kernel);
- }
-
- return 0;
-}
-
-static int fsl_booke_reg_setup(struct op_counter_config *ctr,
- struct op_system_config *sys,
- int num_ctrs)
-{
- int i;
-
- num_counters = num_ctrs;
-
- /* Our counters count up, and "count" refers to
- * how much before the next interrupt, and we interrupt
- * on overflow. So we calculate the starting value
- * which will give us "count" until overflow.
- * Then we set the events on the enabled counters */
- for (i = 0; i < num_counters; ++i)
- reset_value[i] = 0x80000000UL - ctr[i].count;
-
- return 0;
-}
-
-static int fsl_booke_start(struct op_counter_config *ctr)
-{
- int i;
-
- mtmsr(mfmsr() | MSR_PMM);
-
- for (i = 0; i < num_counters; ++i) {
- if (ctr[i].enabled) {
- ctr_write(i, reset_value[i]);
- /* Set each enabled counter to only
- * count when the Mark bit is *not* set */
- set_pmc_marked(i, 1, 0);
- pmc_start_ctr(i, 1);
- } else {
- ctr_write(i, 0);
-
- /* Set the ctr to be stopped */
- pmc_start_ctr(i, 0);
- }
- }
-
- /* Clear the freeze bit, and enable the interrupt.
- * The counters won't actually start until the rfi clears
- * the PMM bit */
- pmc_start_ctrs(1);
-
- oprofile_running = 1;
-
- pr_debug("start on cpu %d, pmgc0 %x\n", smp_processor_id(),
- mfpmr(PMRN_PMGC0));
-
- return 0;
-}
-
-static void fsl_booke_stop(void)
-{
- /* freeze counters */
- pmc_stop_ctrs();
-
- oprofile_running = 0;
-
- pr_debug("stop on cpu %d, pmgc0 %x\n", smp_processor_id(),
- mfpmr(PMRN_PMGC0));
-
- mb();
-}
-
-
-static void fsl_booke_handle_interrupt(struct pt_regs *regs,
- struct op_counter_config *ctr)
-{
- unsigned long pc;
- int is_kernel;
- int val;
- int i;
-
- /* set the PMM bit (see comment below) */
- mtmsr(mfmsr() | MSR_PMM);
-
- pc = regs->nip;
- is_kernel = is_kernel_addr(pc);
-
- for (i = 0; i < num_counters; ++i) {
- val = ctr_read(i);
- if (val < 0) {
- if (oprofile_running && ctr[i].enabled) {
- oprofile_add_ext_sample(pc, regs, i, is_kernel);
- ctr_write(i, reset_value[i]);
- } else {
- ctr_write(i, 0);
- }
- }
- }
-
- /* The freeze bit was set by the interrupt. */
- /* Clear the freeze bit, and reenable the interrupt.
- * The counters won't actually start until the rfi clears
- * the PMM bit */
- pmc_start_ctrs(1);
-}
-
-struct op_powerpc_model op_model_fsl_booke = {
- .reg_setup = fsl_booke_reg_setup,
- .cpu_setup = fsl_booke_cpu_setup,
- .start = fsl_booke_start,
- .stop = fsl_booke_stop,
- .handle_interrupt = fsl_booke_handle_interrupt,
-};
diff --git a/arch/powerpc/oprofile/op_model_fsl_emb.c b/arch/powerpc/oprofile/op_model_fsl_emb.c
new file mode 100644
index 0000000..91596f6
--- /dev/null
+++ b/arch/powerpc/oprofile/op_model_fsl_emb.c
@@ -0,0 +1,369 @@
+/*
+ * Freescale Embedded oprofile support, based on ppc64 oprofile support
+ * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc
+ *
+ * Author: Andy Fleming
+ * Maintainer: Kumar Gala <galak@kernel.crashing.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/oprofile.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/cputable.h>
+#include <asm/reg_fsl_emb.h>
+#include <asm/page.h>
+#include <asm/pmc.h>
+#include <asm/oprofile_impl.h>
+
+static unsigned long reset_value[OP_MAX_COUNTER];
+
+static int num_counters;
+static int oprofile_running;
+
+static inline u32 get_pmlca(int ctr)
+{
+ u32 pmlca;
+
+ switch (ctr) {
+ case 0:
+ pmlca = mfpmr(PMRN_PMLCA0);
+ break;
+ case 1:
+ pmlca = mfpmr(PMRN_PMLCA1);
+ break;
+ case 2:
+ pmlca = mfpmr(PMRN_PMLCA2);
+ break;
+ case 3:
+ pmlca = mfpmr(PMRN_PMLCA3);
+ break;
+ default:
+ panic("Bad ctr number\n");
+ }
+
+ return pmlca;
+}
+
+static inline void set_pmlca(int ctr, u32 pmlca)
+{
+ switch (ctr) {
+ case 0:
+ mtpmr(PMRN_PMLCA0, pmlca);
+ break;
+ case 1:
+ mtpmr(PMRN_PMLCA1, pmlca);
+ break;
+ case 2:
+ mtpmr(PMRN_PMLCA2, pmlca);
+ break;
+ case 3:
+ mtpmr(PMRN_PMLCA3, pmlca);
+ break;
+ default:
+ panic("Bad ctr number\n");
+ }
+}
+
+static inline unsigned int ctr_read(unsigned int i)
+{
+ switch(i) {
+ case 0:
+ return mfpmr(PMRN_PMC0);
+ case 1:
+ return mfpmr(PMRN_PMC1);
+ case 2:
+ return mfpmr(PMRN_PMC2);
+ case 3:
+ return mfpmr(PMRN_PMC3);
+ default:
+ return 0;
+ }
+}
+
+static inline void ctr_write(unsigned int i, unsigned int val)
+{
+ switch(i) {
+ case 0:
+ mtpmr(PMRN_PMC0, val);
+ break;
+ case 1:
+ mtpmr(PMRN_PMC1, val);
+ break;
+ case 2:
+ mtpmr(PMRN_PMC2, val);
+ break;
+ case 3:
+ mtpmr(PMRN_PMC3, val);
+ break;
+ default:
+ break;
+ }
+}
+
+
+static void init_pmc_stop(int ctr)
+{
+ u32 pmlca = (PMLCA_FC | PMLCA_FCS | PMLCA_FCU |
+ PMLCA_FCM1 | PMLCA_FCM0);
+ u32 pmlcb = 0;
+
+ switch (ctr) {
+ case 0:
+ mtpmr(PMRN_PMLCA0, pmlca);
+ mtpmr(PMRN_PMLCB0, pmlcb);
+ break;
+ case 1:
+ mtpmr(PMRN_PMLCA1, pmlca);
+ mtpmr(PMRN_PMLCB1, pmlcb);
+ break;
+ case 2:
+ mtpmr(PMRN_PMLCA2, pmlca);
+ mtpmr(PMRN_PMLCB2, pmlcb);
+ break;
+ case 3:
+ mtpmr(PMRN_PMLCA3, pmlca);
+ mtpmr(PMRN_PMLCB3, pmlcb);
+ break;
+ default:
+ panic("Bad ctr number!\n");
+ }
+}
+
+static void set_pmc_event(int ctr, int event)
+{
+ u32 pmlca;
+
+ pmlca = get_pmlca(ctr);
+
+ pmlca = (pmlca & ~PMLCA_EVENT_MASK) |
+ ((event << PMLCA_EVENT_SHIFT) &
+ PMLCA_EVENT_MASK);
+
+ set_pmlca(ctr, pmlca);
+}
+
+static void set_pmc_user_kernel(int ctr, int user, int kernel)
+{
+ u32 pmlca;
+
+ pmlca = get_pmlca(ctr);
+
+ if(user)
+ pmlca &= ~PMLCA_FCU;
+ else
+ pmlca |= PMLCA_FCU;
+
+ if(kernel)
+ pmlca &= ~PMLCA_FCS;
+ else
+ pmlca |= PMLCA_FCS;
+
+ set_pmlca(ctr, pmlca);
+}
+
+static void set_pmc_marked(int ctr, int mark0, int mark1)
+{
+ u32 pmlca = get_pmlca(ctr);
+
+ if(mark0)
+ pmlca &= ~PMLCA_FCM0;
+ else
+ pmlca |= PMLCA_FCM0;
+
+ if(mark1)
+ pmlca &= ~PMLCA_FCM1;
+ else
+ pmlca |= PMLCA_FCM1;
+
+ set_pmlca(ctr, pmlca);
+}
+
+static void pmc_start_ctr(int ctr, int enable)
+{
+ u32 pmlca = get_pmlca(ctr);
+
+ pmlca &= ~PMLCA_FC;
+
+ if (enable)
+ pmlca |= PMLCA_CE;
+ else
+ pmlca &= ~PMLCA_CE;
+
+ set_pmlca(ctr, pmlca);
+}
+
+static void pmc_start_ctrs(int enable)
+{
+ u32 pmgc0 = mfpmr(PMRN_PMGC0);
+
+ pmgc0 &= ~PMGC0_FAC;
+ pmgc0 |= PMGC0_FCECE;
+
+ if (enable)
+ pmgc0 |= PMGC0_PMIE;
+ else
+ pmgc0 &= ~PMGC0_PMIE;
+
+ mtpmr(PMRN_PMGC0, pmgc0);
+}
+
+static void pmc_stop_ctrs(void)
+{
+ u32 pmgc0 = mfpmr(PMRN_PMGC0);
+
+ pmgc0 |= PMGC0_FAC;
+
+ pmgc0 &= ~(PMGC0_PMIE | PMGC0_FCECE);
+
+ mtpmr(PMRN_PMGC0, pmgc0);
+}
+
+static void dump_pmcs(void)
+{
+ printk("pmgc0: %x\n", mfpmr(PMRN_PMGC0));
+ printk("pmc\t\tpmlca\t\tpmlcb\n");
+ printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC0),
+ mfpmr(PMRN_PMLCA0), mfpmr(PMRN_PMLCB0));
+ printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC1),
+ mfpmr(PMRN_PMLCA1), mfpmr(PMRN_PMLCB1));
+ printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC2),
+ mfpmr(PMRN_PMLCA2), mfpmr(PMRN_PMLCB2));
+ printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC3),
+ mfpmr(PMRN_PMLCA3), mfpmr(PMRN_PMLCB3));
+}
+
+static int fsl_emb_cpu_setup(struct op_counter_config *ctr)
+{
+ int i;
+
+ /* freeze all counters */
+ pmc_stop_ctrs();
+
+ for (i = 0;i < num_counters;i++) {
+ init_pmc_stop(i);
+
+ set_pmc_event(i, ctr[i].event);
+
+ set_pmc_user_kernel(i, ctr[i].user, ctr[i].kernel);
+ }
+
+ return 0;
+}
+
+static int fsl_emb_reg_setup(struct op_counter_config *ctr,
+ struct op_system_config *sys,
+ int num_ctrs)
+{
+ int i;
+
+ num_counters = num_ctrs;
+
+ /* Our counters count up, and "count" refers to
+ * how much before the next interrupt, and we interrupt
+ * on overflow. So we calculate the starting value
+ * which will give us "count" until overflow.
+ * Then we set the events on the enabled counters */
+ for (i = 0; i < num_counters; ++i)
+ reset_value[i] = 0x80000000UL - ctr[i].count;
+
+ return 0;
+}
+
+static int fsl_emb_start(struct op_counter_config *ctr)
+{
+ int i;
+
+ mtmsr(mfmsr() | MSR_PMM);
+
+ for (i = 0; i < num_counters; ++i) {
+ if (ctr[i].enabled) {
+ ctr_write(i, reset_value[i]);
+ /* Set each enabled counter to only
+ * count when the Mark bit is *not* set */
+ set_pmc_marked(i, 1, 0);
+ pmc_start_ctr(i, 1);
+ } else {
+ ctr_write(i, 0);
+
+ /* Set the ctr to be stopped */
+ pmc_start_ctr(i, 0);
+ }
+ }
+
+ /* Clear the freeze bit, and enable the interrupt.
+ * The counters won't actually start until the rfi clears
+ * the PMM bit */
+ pmc_start_ctrs(1);
+
+ oprofile_running = 1;
+
+ pr_debug("start on cpu %d, pmgc0 %x\n", smp_processor_id(),
+ mfpmr(PMRN_PMGC0));
+
+ return 0;
+}
+
+static void fsl_emb_stop(void)
+{
+ /* freeze counters */
+ pmc_stop_ctrs();
+
+ oprofile_running = 0;
+
+ pr_debug("stop on cpu %d, pmgc0 %x\n", smp_processor_id(),
+ mfpmr(PMRN_PMGC0));
+
+ mb();
+}
+
+
+static void fsl_emb_handle_interrupt(struct pt_regs *regs,
+ struct op_counter_config *ctr)
+{
+ unsigned long pc;
+ int is_kernel;
+ int val;
+ int i;
+
+ /* set the PMM bit (see comment below) */
+ mtmsr(mfmsr() | MSR_PMM);
+
+ pc = regs->nip;
+ is_kernel = is_kernel_addr(pc);
+
+ for (i = 0; i < num_counters; ++i) {
+ val = ctr_read(i);
+ if (val < 0) {
+ if (oprofile_running && ctr[i].enabled) {
+ oprofile_add_ext_sample(pc, regs, i, is_kernel);
+ ctr_write(i, reset_value[i]);
+ } else {
+ ctr_write(i, 0);
+ }
+ }
+ }
+
+ /* The freeze bit was set by the interrupt. */
+ /* Clear the freeze bit, and reenable the interrupt.
+ * The counters won't actually start until the rfi clears
+ * the PMM bit */
+ pmc_start_ctrs(1);
+}
+
+struct op_powerpc_model op_model_fsl_emb = {
+ .reg_setup = fsl_emb_reg_setup,
+ .cpu_setup = fsl_emb_cpu_setup,
+ .start = fsl_emb_start,
+ .stop = fsl_emb_stop,
+ .handle_interrupt = fsl_emb_handle_interrupt,
+};
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 7fc4110..dce0d87 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -94,6 +94,7 @@ config 8xx
bool
config E500
+ select FSL_EMB_PERFMON
bool
config PPC_FPU
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index 528ef18..1e79673 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -46,7 +46,7 @@ enum powerpc_oprofile_type {
PPC_OPROFILE_RS64 = 1,
PPC_OPROFILE_POWER4 = 2,
PPC_OPROFILE_G4 = 3,
- PPC_OPROFILE_BOOKE = 4,
+ PPC_OPROFILE_FSL_EMB = 4,
PPC_OPROFILE_CELL = 5,
PPC_OPROFILE_PA6T = 6,
};
diff --git a/include/asm-powerpc/oprofile_impl.h b/include/asm-powerpc/oprofile_impl.h
index 938fefb..95035c6 100644
--- a/include/asm-powerpc/oprofile_impl.h
+++ b/include/asm-powerpc/oprofile_impl.h
@@ -54,7 +54,7 @@ struct op_powerpc_model {
int num_counters;
};
-extern struct op_powerpc_model op_model_fsl_booke;
+extern struct op_powerpc_model op_model_fsl_emb;
extern struct op_powerpc_model op_model_rs64;
extern struct op_powerpc_model op_model_power4;
extern struct op_powerpc_model op_model_7450;
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h
index 2408a29..0d62389 100644
--- a/include/asm-powerpc/reg.h
+++ b/include/asm-powerpc/reg.h
@@ -18,6 +18,10 @@
#include <asm/reg_booke.h>
#endif /* CONFIG_BOOKE || CONFIG_40x */
+#ifdef CONFIG_FSL_EMB_PERFMON
+#include <asm/reg_fsl_emb.h>
+#endif
+
#ifdef CONFIG_8xx
#include <asm/reg_8xx.h>
#endif /* CONFIG_8xx */
diff --git a/include/asm-powerpc/reg_booke.h b/include/asm-powerpc/reg_booke.h
index 0405ef4..cf54a3f 100644
--- a/include/asm-powerpc/reg_booke.h
+++ b/include/asm-powerpc/reg_booke.h
@@ -9,68 +9,6 @@
#ifndef __ASM_POWERPC_REG_BOOKE_H__
#define __ASM_POWERPC_REG_BOOKE_H__
-#ifndef __ASSEMBLY__
-/* Performance Monitor Registers */
-#define mfpmr(rn) ({unsigned int rval; \
- asm volatile("mfpmr %0," __stringify(rn) \
- : "=r" (rval)); rval;})
-#define mtpmr(rn, v) asm volatile("mtpmr " __stringify(rn) ",%0" : : "r" (v))
-#endif /* __ASSEMBLY__ */
-
-/* Freescale Book E Performance Monitor APU Registers */
-#define PMRN_PMC0 0x010 /* Performance Monitor Counter 0 */
-#define PMRN_PMC1 0x011 /* Performance Monitor Counter 1 */
-#define PMRN_PMC2 0x012 /* Performance Monitor Counter 1 */
-#define PMRN_PMC3 0x013 /* Performance Monitor Counter 1 */
-#define PMRN_PMLCA0 0x090 /* PM Local Control A0 */
-#define PMRN_PMLCA1 0x091 /* PM Local Control A1 */
-#define PMRN_PMLCA2 0x092 /* PM Local Control A2 */
-#define PMRN_PMLCA3 0x093 /* PM Local Control A3 */
-
-#define PMLCA_FC 0x80000000 /* Freeze Counter */
-#define PMLCA_FCS 0x40000000 /* Freeze in Supervisor */
-#define PMLCA_FCU 0x20000000 /* Freeze in User */
-#define PMLCA_FCM1 0x10000000 /* Freeze when PMM==1 */
-#define PMLCA_FCM0 0x08000000 /* Freeze when PMM==0 */
-#define PMLCA_CE 0x04000000 /* Condition Enable */
-
-#define PMLCA_EVENT_MASK 0x007f0000 /* Event field */
-#define PMLCA_EVENT_SHIFT 16
-
-#define PMRN_PMLCB0 0x110 /* PM Local Control B0 */
-#define PMRN_PMLCB1 0x111 /* PM Local Control B1 */
-#define PMRN_PMLCB2 0x112 /* PM Local Control B2 */
-#define PMRN_PMLCB3 0x113 /* PM Local Control B3 */
-
-#define PMLCB_THRESHMUL_MASK 0x0700 /* Threshhold Multiple Field */
-#define PMLCB_THRESHMUL_SHIFT 8
-
-#define PMLCB_THRESHOLD_MASK 0x003f /* Threshold Field */
-#define PMLCB_THRESHOLD_SHIFT 0
-
-#define PMRN_PMGC0 0x190 /* PM Global Control 0 */
-
-#define PMGC0_FAC 0x80000000 /* Freeze all Counters */
-#define PMGC0_PMIE 0x40000000 /* Interrupt Enable */
-#define PMGC0_FCECE 0x20000000 /* Freeze countes on
- Enabled Condition or
- Event */
-
-#define PMRN_UPMC0 0x000 /* User Performance Monitor Counter 0 */
-#define PMRN_UPMC1 0x001 /* User Performance Monitor Counter 1 */
-#define PMRN_UPMC2 0x002 /* User Performance Monitor Counter 1 */
-#define PMRN_UPMC3 0x003 /* User Performance Monitor Counter 1 */
-#define PMRN_UPMLCA0 0x080 /* User PM Local Control A0 */
-#define PMRN_UPMLCA1 0x081 /* User PM Local Control A1 */
-#define PMRN_UPMLCA2 0x082 /* User PM Local Control A2 */
-#define PMRN_UPMLCA3 0x083 /* User PM Local Control A3 */
-#define PMRN_UPMLCB0 0x100 /* User PM Local Control B0 */
-#define PMRN_UPMLCB1 0x101 /* User PM Local Control B1 */
-#define PMRN_UPMLCB2 0x102 /* User PM Local Control B2 */
-#define PMRN_UPMLCB3 0x103 /* User PM Local Control B3 */
-#define PMRN_UPMGC0 0x180 /* User PM Global Control 0 */
-
-
/* Machine State Register (MSR) Fields */
#define MSR_UCLE (1<<26) /* User-mode cache lock enable */
#define MSR_SPE (1<<25) /* Enable SPE */
diff --git a/include/asm-powerpc/reg_fsl_emb.h b/include/asm-powerpc/reg_fsl_emb.h
new file mode 100644
index 0000000..1e180a5
--- /dev/null
+++ b/include/asm-powerpc/reg_fsl_emb.h
@@ -0,0 +1,72 @@
+/*
+ * Contains register definitions for the Freescale Embedded Performance
+ * Monitor.
+ */
+#ifdef __KERNEL__
+#ifndef __ASM_POWERPC_REG_FSL_EMB_H__
+#define __ASM_POWERPC_REG_FSL_EMB_H__
+
+#ifndef __ASSEMBLY__
+/* Performance Monitor Registers */
+#define mfpmr(rn) ({unsigned int rval; \
+ asm volatile("mfpmr %0," __stringify(rn) \
+ : "=r" (rval)); rval;})
+#define mtpmr(rn, v) asm volatile("mtpmr " __stringify(rn) ",%0" : : "r" (v))
+#endif /* __ASSEMBLY__ */
+
+/* Freescale Book E Performance Monitor APU Registers */
+#define PMRN_PMC0 0x010 /* Performance Monitor Counter 0 */
+#define PMRN_PMC1 0x011 /* Performance Monitor Counter 1 */
+#define PMRN_PMC2 0x012 /* Performance Monitor Counter 1 */
+#define PMRN_PMC3 0x013 /* Performance Monitor Counter 1 */
+#define PMRN_PMLCA0 0x090 /* PM Local Control A0 */
+#define PMRN_PMLCA1 0x091 /* PM Local Control A1 */
+#define PMRN_PMLCA2 0x092 /* PM Local Control A2 */
+#define PMRN_PMLCA3 0x093 /* PM Local Control A3 */
+
+#define PMLCA_FC 0x80000000 /* Freeze Counter */
+#define PMLCA_FCS 0x40000000 /* Freeze in Supervisor */
+#define PMLCA_FCU 0x20000000 /* Freeze in User */
+#define PMLCA_FCM1 0x10000000 /* Freeze when PMM==1 */
+#define PMLCA_FCM0 0x08000000 /* Freeze when PMM==0 */
+#define PMLCA_CE 0x04000000 /* Condition Enable */
+
+#define PMLCA_EVENT_MASK 0x007f0000 /* Event field */
+#define PMLCA_EVENT_SHIFT 16
+
+#define PMRN_PMLCB0 0x110 /* PM Local Control B0 */
+#define PMRN_PMLCB1 0x111 /* PM Local Control B1 */
+#define PMRN_PMLCB2 0x112 /* PM Local Control B2 */
+#define PMRN_PMLCB3 0x113 /* PM Local Control B3 */
+
+#define PMLCB_THRESHMUL_MASK 0x0700 /* Threshhold Multiple Field */
+#define PMLCB_THRESHMUL_SHIFT 8
+
+#define PMLCB_THRESHOLD_MASK 0x003f /* Threshold Field */
+#define PMLCB_THRESHOLD_SHIFT 0
+
+#define PMRN_PMGC0 0x190 /* PM Global Control 0 */
+
+#define PMGC0_FAC 0x80000000 /* Freeze all Counters */
+#define PMGC0_PMIE 0x40000000 /* Interrupt Enable */
+#define PMGC0_FCECE 0x20000000 /* Freeze countes on
+ Enabled Condition or
+ Event */
+
+#define PMRN_UPMC0 0x000 /* User Performance Monitor Counter 0 */
+#define PMRN_UPMC1 0x001 /* User Performance Monitor Counter 1 */
+#define PMRN_UPMC2 0x002 /* User Performance Monitor Counter 1 */
+#define PMRN_UPMC3 0x003 /* User Performance Monitor Counter 1 */
+#define PMRN_UPMLCA0 0x080 /* User PM Local Control A0 */
+#define PMRN_UPMLCA1 0x081 /* User PM Local Control A1 */
+#define PMRN_UPMLCA2 0x082 /* User PM Local Control A2 */
+#define PMRN_UPMLCA3 0x083 /* User PM Local Control A3 */
+#define PMRN_UPMLCB0 0x100 /* User PM Local Control B0 */
+#define PMRN_UPMLCB1 0x101 /* User PM Local Control B1 */
+#define PMRN_UPMLCB2 0x102 /* User PM Local Control B2 */
+#define PMRN_UPMLCB3 0x103 /* User PM Local Control B3 */
+#define PMRN_UPMGC0 0x180 /* User PM Global Control 0 */
+
+
+#endif /* __ASM_POWERPC_REG_FSL_EMB_H__ */
+#endif /* __KERNEL__ */
--
1.5.0.2.230.gfbe3d-dirty
^ permalink raw reply related
* [PATCH] Add oprofile support for e300
From: Andy Fleming @ 2008-02-04 23:14 UTC (permalink / raw)
To: linuxppc-dev, galak
The e300 c3 and c4 variants support hardware performance monitor counters which
are identical to those found in the e500.
Signed-off-by: Andy Fleming <afleming@freescale.com>
---
arch/powerpc/kernel/cputable.c | 4 ++--
arch/powerpc/platforms/Kconfig | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index c8af497..2a8f5cc 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -961,7 +961,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.cpu_setup = __setup_cpu_603,
.num_pmcs = 4,
.oprofile_cpu_type = "ppc/e300",
- .oprofile_type = PPC_OPROFILE_BOOKE,
+ .oprofile_type = PPC_OPROFILE_FSL_EMB,
.platform = "ppc603",
},
{ /* e300c4 (e300c1, plus one IU) */
@@ -976,7 +976,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.machine_check = machine_check_generic,
.num_pmcs = 4,
.oprofile_cpu_type = "ppc/e300",
- .oprofile_type = PPC_OPROFILE_BOOKE,
+ .oprofile_type = PPC_OPROFILE_FSL_EMB,
.platform = "ppc603",
},
{ /* default match, we assume split I/D cache & TB (non-601)... */
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index fdce10c..045b8c8 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -24,6 +24,7 @@ config PPC_83xx
select MPC83xx
select IPIC
select WANT_DEVICE_TREE
+ select FSL_EMB_PERFMON
config PPC_86xx
bool "Freescale 86xx"
--
1.5.0.2.230.gfbe3d-dirty
^ permalink raw reply related
* Re: [PATCH 2/2] ehea: add memory remove hotplug support
From: Michael Ellerman @ 2008-02-04 23:14 UTC (permalink / raw)
To: Jan-Bernd Themann
Cc: Thomas Klein, Jeff Garzik, Jan-Bernd Themann, netdev,
linux-kernel, linux-ppc, Christoph Raisch, Marcus Eder
In-Reply-To: <200802041624.31228.ossthema@de.ibm.com>
[-- Attachment #1: Type: text/plain, Size: 1706 bytes --]
On Mon, 2008-02-04 at 16:24 +0100, Jan-Bernd Themann wrote:
> On Monday 04 February 2008 15:46, Michael Ellerman wrote:
> > On Mon, 2008-02-04 at 14:04 +0100, Jan-Bernd Themann wrote:
> > > Add memory remove hotplug support
>
> > > @@ -3559,6 +3578,10 @@ int __init ehea_module_init(void)
> > > if (ret)
> > > ehea_info("failed registering reboot notifier");
> > >
> > > + ret = register_memory_notifier(&ehea_mem_nb);
> > > + if (ret)
> > > + ehea_info("failed registering memory remove notifier");
> > >
> > > ret = crash_shutdown_register(&ehea_crash_handler);
> > > if (ret)
> > > ehea_info("failed registering crash handler");
> >
> > You don't do anything except print a message if the registration fails.
> > What happens when someone tries to remove memory but the memory notifier
> > wasn't registered properly? Bang?
>
> In case the registration fails and somebody tries to free memory:
> - Driver will not remove the affected memory from the eHEA memory region
> --> Firmware (phyp) can not free that memory (as marked as used)
> --> Therefore the removed memory could not be used in an other partition
>
> It makes sense to allow the driver to work anyway. Having no ethernet
> would not really be a good alternative.
Yeah I agree. I wasn't clear from the patch that no notifier -> no
memory removed. Rather than, no notifier -> memory removed and ehea
isn't told about it.
cheers
--
Michael Ellerman
OzLabs, IBM Australia Development Lab
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)
We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: Commit for mm/page_alloc.c breaks boot process on my machine
From: Michael Ellerman @ 2008-02-04 23:30 UTC (permalink / raw)
To: Gerhard Pircher; +Cc: Mel Gorman, linuxppc-dev, linux-kernel
In-Reply-To: <20080204222047.243670@gmx.net>
[-- Attachment #1: Type: text/plain, Size: 2148 bytes --]
On Mon, 2008-02-04 at 23:20 +0100, Gerhard Pircher wrote:
> -------- Original-Nachricht --------
> > Datum: Mon, 4 Feb 2008 10:42:32 +0000
> > Von: Mel Gorman <mel@csn.ul.ie>
> > An: Gerhard Pircher <gerhard_pircher@gmx.net>
> > CC: linux-kernel@vger.kernel.org, linuxppc-dev@ozlabs.org
> > Betreff: Re: Commit for mm/page_alloc.c breaks boot process on my machine
>
> > > > > > 2. Any chance of seeing a dmesg log?
> > > > > That's a little bit of a problem. The kernel log in memory doesn't
> > > > > show any kernel oops, but is also fragmented (small fragments seem
> > > > > to have been overwritten with 0x0).
> > > >
> > > > err, that doesn't sound very healthy.
> > >
> > > Yeah, I know. But the platform code hasn't changed much when porting it
> > > from arch/ppc to arch/powerpc. That's why I'm a little bit lost in this
> > > case. :-)
> > >
> >
> > I'm at a bit of a loss to guess what might have changed in powerpc code
> > that would explain this. I've added the linuxppc-dev mailing list in
> > case they can make a guess.
> Yes, I'll try to get some comments on the linuxppc-dev mailing list.
>
> > I think you are also going to need to start bisecting searching
> > specifically for the patch that causes these overwrites.
> I think I had a similar problem with kernel v2.6.23, too and therefore
> waited for kernel 2.6.24. So the problem may exist since a long time.
>
> > It's a virtual address so it depends on the value of CONFIG_KERNEL_START
> > as to whether this is a user program address or not.
> AFAIK start_kernel() is called very early in the boot process, were no
> user or kernel thread is active. I also wonder why the kernel crashes when
> the mem boot option is used. Let's see what the linuxppc-dev people say.
Can you post a fresh bug report? There's lots of details missing from
the email you forwarded.
cheers
--
Michael Ellerman
OzLabs, IBM Australia Development Lab
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)
We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: Commit for mm/page_alloc.c breaks boot process on my machine
From: Benjamin Herrenschmidt @ 2008-02-05 0:01 UTC (permalink / raw)
To: Mel Gorman; +Cc: linux-kernel, linuxppc-dev
In-Reply-To: <20080204104232.GB29484@csn.ul.ie>
>
> It's a virtual address so it depends on the value of CONFIG_KERNEL_START
> as to whether this is a user program address or not.
Shouldn't it be PAGE_OFFSET ? I mean, CONFIG_KERNEL_START should work
on powerpc, but still...
Ben.
^ permalink raw reply
* Re: [PATCH 1/4] Search for and publish cell OF platform devices earlier
From: Benjamin Herrenschmidt @ 2008-02-05 0:19 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, cbe-oss-dev
In-Reply-To: <3ce7be4c77581ce103a8da9f33a734270c9dc6e8.1201240265.git.michael@ellerman.id.au>
On Fri, 2008-01-25 at 16:59 +1100, Michael Ellerman wrote:
> Currently cell publishes OF devices at device_initcall() time, which
> means the earliest a driver can bind to a device is also device_initcall()
> time. We have a driver we want to register before other devices, so
> publish the devices at subsys_initcall() time.
>
> This should not cause any behaviour change for existing drivers, as they
> are still bound at device_initcall() time.
>
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
> arch/powerpc/platforms/cell/setup.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
> index e6534b5..a7f609b 100644
> --- a/arch/powerpc/platforms/cell/setup.c
> +++ b/arch/powerpc/platforms/cell/setup.c
> @@ -98,7 +98,7 @@ static int __init cell_publish_devices(void)
> }
> return 0;
> }
> -machine_device_initcall(cell, cell_publish_devices);
> +machine_subsys_initcall(cell, cell_publish_devices);
>
> static void cell_mpic_cascade(unsigned int irq, struct irq_desc *desc)
> {
^ permalink raw reply
* Re: [PATCH 2/4] Create and hook up of_platform_device_shutdown
From: Benjamin Herrenschmidt @ 2008-02-05 0:19 UTC (permalink / raw)
To: Michael Ellerman; +Cc: tnt, davem, linuxppc-dev, sparclinux, cbe-oss-dev, m8
In-Reply-To: <bf48a30aa9f58fa6e153f679eb0eb6a4864ebdc3.1201240265.git.michael@ellerman.id.au>
On Fri, 2008-01-25 at 16:59 +1100, Michael Ellerman wrote:
> Although of_platform_device's can have a shutdown routine, at the moment
> the bus code doesn't actually call it. So add the required glue to
> hook the shutdown routine.
>
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
> drivers/of/platform.c | 10 ++++++++++
> 1 files changed, 10 insertions(+), 0 deletions(-)
>
>
> CC various folks who've written/touched of_platform_drivers which already
> have shutdown routines. These routines have never been called so they're
> about to get their first testing.
>
> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> index b47bb2d..ca09a63 100644
> --- a/drivers/of/platform.c
> +++ b/drivers/of/platform.c
> @@ -85,6 +85,15 @@ static int of_platform_device_resume(struct device * dev)
> return error;
> }
>
> +static void of_platform_device_shutdown(struct device *dev)
> +{
> + struct of_device *of_dev = to_of_device(dev);
> + struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
> +
> + if (dev->driver && drv->shutdown)
> + drv->shutdown(of_dev);
> +}
> +
> int of_bus_type_init(struct bus_type *bus, const char *name)
> {
> bus->name = name;
> @@ -93,6 +102,7 @@ int of_bus_type_init(struct bus_type *bus, const char *name)
> bus->remove = of_platform_device_remove;
> bus->suspend = of_platform_device_suspend;
> bus->resume = of_platform_device_resume;
> + bus->shutdown = of_platform_device_shutdown;
> return bus_register(bus);
> }
>
^ permalink raw reply
* Re: [PATCH] Add oprofile support for e300
From: Andy Fleming @ 2008-02-05 0:19 UTC (permalink / raw)
To: Andy Fleming; +Cc: linuxppc-dev
In-Reply-To: <12021668462559-git-send-email-afleming@freescale.com>
On Feb 4, 2008, at 17:14, Andy Fleming wrote:
> The e300 c3 and c4 variants support hardware performance monitor
> counters which
> are identical to those found in the e500.
Please ignore. I will send a new version that includes all the
changes I apparently missed a change I had already committed.
I will send a new version of both oprofile patches so as to make the
first patch easier to read, too.
^ permalink raw reply
* Re: [PATCH 3/4] Convert axon_msi to an of_platform driver
From: Benjamin Herrenschmidt @ 2008-02-05 0:20 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, cbe-oss-dev
In-Reply-To: <a42b0e1b5224f8f2e6f87ab1bbe520a55be85e98.1201240265.git.michael@ellerman.id.au>
On Fri, 2008-01-25 at 16:59 +1100, Michael Ellerman wrote:
> Now that we create of_platform devices earlier on cell, we can make the
> axon_msi driver an of_platform driver. This makes the code cleaner in
> several ways, and most importantly means we have a struct device.
>
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
> arch/powerpc/platforms/cell/axon_msi.c | 76 ++++++++++++++-----------------
> 1 files changed, 34 insertions(+), 42 deletions(-)
>
> diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
> index 095988f..ea3dc8c 100644
> --- a/arch/powerpc/platforms/cell/axon_msi.c
> +++ b/arch/powerpc/platforms/cell/axon_msi.c
> @@ -13,7 +13,7 @@
> #include <linux/kernel.h>
> #include <linux/pci.h>
> #include <linux/msi.h>
> -#include <linux/reboot.h>
> +#include <linux/of_platform.h>
>
> #include <asm/dcr.h>
> #include <asm/machdep.h>
> @@ -67,12 +67,9 @@ struct axon_msic {
> struct irq_host *irq_host;
> __le32 *fifo;
> dcr_host_t dcr_host;
> - struct list_head list;
> u32 read_offset;
> };
>
> -static LIST_HEAD(axon_msic_list);
> -
> static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val)
> {
> pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n);
> @@ -292,30 +289,25 @@ static struct irq_host_ops msic_host_ops = {
> .map = msic_host_map,
> };
>
> -static int axon_msi_notify_reboot(struct notifier_block *nb,
> - unsigned long code, void *data)
> +static int axon_msi_shutdown(struct of_device *device)
> {
> - struct axon_msic *msic;
> + struct axon_msic *msic = device->dev.platform_data;
> u32 tmp;
>
> - list_for_each_entry(msic, &axon_msic_list, list) {
> - pr_debug("axon_msi: disabling %s\n",
> - msic->irq_host->of_node->full_name);
> - tmp = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
> - tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
> - msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
> - }
> + pr_debug("axon_msi: disabling %s\n",
> + msic->irq_host->of_node->full_name);
> + tmp = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
> + tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
> + msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
>
> return 0;
> }
>
> -static struct notifier_block axon_msi_reboot_notifier = {
> - .notifier_call = axon_msi_notify_reboot
> -};
> -
> -static int axon_msi_setup_one(struct device_node *dn)
> +static int axon_msi_probe(struct of_device *device,
> + const struct of_device_id *device_id)
> {
> struct page *page;
> + struct device_node *dn = device->node;
> struct axon_msic *msic;
> unsigned int virq;
> int dcr_base, dcr_len;
> @@ -385,7 +377,11 @@ static int axon_msi_setup_one(struct device_node *dn)
> MSIC_CTRL_IRQ_ENABLE | MSIC_CTRL_ENABLE |
> MSIC_CTRL_FIFO_SIZE);
>
> - list_add(&msic->list, &axon_msic_list);
> + device->dev.platform_data = msic;
> +
> + ppc_md.setup_msi_irqs = axon_msi_setup_msi_irqs;
> + ppc_md.teardown_msi_irqs = axon_msi_teardown_msi_irqs;
> + ppc_md.msi_check_device = axon_msi_check_device;
>
> printk(KERN_DEBUG "axon_msi: setup MSIC on %s\n", dn->full_name);
>
> @@ -402,28 +398,24 @@ out:
> return -1;
> }
>
> -static int axon_msi_init(void)
> -{
> - struct device_node *dn;
> - int found = 0;
> -
> - pr_debug("axon_msi: initialising ...\n");
> -
> - for_each_compatible_node(dn, NULL, "ibm,axon-msic") {
> - if (axon_msi_setup_one(dn) == 0)
> - found++;
> - }
> -
> - if (found) {
> - ppc_md.setup_msi_irqs = axon_msi_setup_msi_irqs;
> - ppc_md.teardown_msi_irqs = axon_msi_teardown_msi_irqs;
> - ppc_md.msi_check_device = axon_msi_check_device;
> -
> - register_reboot_notifier(&axon_msi_reboot_notifier);
> +static const struct of_device_id axon_msi_device_id[] = {
> + {
> + .compatible = "ibm,axon-msic"
> + },
> + {}
> +};
>
> - pr_debug("axon_msi: registered callbacks!\n");
> - }
> +static struct of_platform_driver axon_msi_driver = {
> + .match_table = axon_msi_device_id,
> + .probe = axon_msi_probe,
> + .shutdown = axon_msi_shutdown,
> + .driver = {
> + .name = "axon-msi"
> + },
> +};
>
> - return 0;
> +static int __init axon_msi_init(void)
> +{
> + return of_register_platform_driver(&axon_msi_driver);
> }
> -arch_initcall(axon_msi_init);
> +subsys_initcall(axon_msi_init);
> --
> 1.5.2.rc1.1884.g59b20
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH 4/4] Avoid DMA exception when using axon_msi with IOMMU
From: Benjamin Herrenschmidt @ 2008-02-05 0:21 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, cbe-oss-dev
In-Reply-To: <f1b51505f34145d7b096fef167c14c4409f0baf6.1201240265.git.michael@ellerman.id.au>
On Fri, 2008-01-25 at 16:59 +1100, Michael Ellerman wrote:
> There's a brown-paper-bag bug in axon_msi, we pass the address of our
> FIFO directly to the hardware, without DMA mapping it. This leads to
> DMA exceptions if you enable MSI & the IOMMU.
>
> The fix is to correctly DMA map the fifo, dma_alloc_coherent() does
> what we want - and we need to track the virt & phys addresses.
>
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
> arch/powerpc/platforms/cell/axon_msi.c | 21 ++++++++++-----------
> 1 files changed, 10 insertions(+), 11 deletions(-)
>
> diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
> index ea3dc8c..b9a97c4 100644
> --- a/arch/powerpc/platforms/cell/axon_msi.c
> +++ b/arch/powerpc/platforms/cell/axon_msi.c
> @@ -65,7 +65,8 @@
>
> struct axon_msic {
> struct irq_host *irq_host;
> - __le32 *fifo;
> + __le32 *fifo_virt;
> + dma_addr_t fifo_phys;
> dcr_host_t dcr_host;
> u32 read_offset;
> };
> @@ -91,7 +92,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
>
> while (msic->read_offset != write_offset) {
> idx = msic->read_offset / sizeof(__le32);
> - msi = le32_to_cpu(msic->fifo[idx]);
> + msi = le32_to_cpu(msic->fifo_virt[idx]);
> msi &= 0xFFFF;
>
> pr_debug("axon_msi: woff %x roff %x msi %x\n",
> @@ -306,7 +307,6 @@ static int axon_msi_shutdown(struct of_device *device)
> static int axon_msi_probe(struct of_device *device,
> const struct of_device_id *device_id)
> {
> - struct page *page;
> struct device_node *dn = device->node;
> struct axon_msic *msic;
> unsigned int virq;
> @@ -338,16 +338,14 @@ static int axon_msi_probe(struct of_device *device,
> goto out_free_msic;
> }
>
> - page = alloc_pages_node(of_node_to_nid(dn), GFP_KERNEL,
> - get_order(MSIC_FIFO_SIZE_BYTES));
> - if (!page) {
> + msic->fifo_virt = dma_alloc_coherent(&device->dev, MSIC_FIFO_SIZE_BYTES,
> + &msic->fifo_phys, GFP_KERNEL);
> + if (!msic->fifo_virt) {
> printk(KERN_ERR "axon_msi: couldn't allocate fifo for %s\n",
> dn->full_name);
> goto out_free_msic;
> }
>
> - msic->fifo = page_address(page);
> -
> msic->irq_host = irq_alloc_host(of_node_get(dn), IRQ_HOST_MAP_NOMAP,
> NR_IRQS, &msic_host_ops, 0);
> if (!msic->irq_host) {
> @@ -370,9 +368,9 @@ static int axon_msi_probe(struct of_device *device,
> pr_debug("axon_msi: irq 0x%x setup for axon_msi\n", virq);
>
> /* Enable the MSIC hardware */
> - msic_dcr_write(msic, MSIC_BASE_ADDR_HI_REG, (u64)msic->fifo >> 32);
> + msic_dcr_write(msic, MSIC_BASE_ADDR_HI_REG, msic->fifo_phys >> 32);
> msic_dcr_write(msic, MSIC_BASE_ADDR_LO_REG,
> - (u64)msic->fifo & 0xFFFFFFFF);
> + msic->fifo_phys & 0xFFFFFFFF);
> msic_dcr_write(msic, MSIC_CTRL_REG,
> MSIC_CTRL_IRQ_ENABLE | MSIC_CTRL_ENABLE |
> MSIC_CTRL_FIFO_SIZE);
> @@ -390,7 +388,8 @@ static int axon_msi_probe(struct of_device *device,
> out_free_host:
> kfree(msic->irq_host);
> out_free_fifo:
> - __free_pages(virt_to_page(msic->fifo), get_order(MSIC_FIFO_SIZE_BYTES));
> + dma_free_coherent(&device->dev, MSIC_FIFO_SIZE_BYTES, msic->fifo_virt,
> + msic->fifo_phys);
> out_free_msic:
> kfree(msic);
> out:
^ permalink raw reply
* Re: [PATCH 2/3] Allocate the hash table under 1G on cell
From: Benjamin Herrenschmidt @ 2008-02-05 0:23 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, cbe-oss-dev
In-Reply-To: <f7985e5b32565961444283819eaeeda86f471fc8.1201257905.git.michael@ellerman.id.au>
On Fri, 2008-01-25 at 21:45 +1100, Michael Ellerman wrote:
> In order to support our IOMMU performance trick, we need the hash table to be
> inside the DMA window. This is usually 2G, but let's make sure the hash table
> is under 1G as that will satisfy the IOMMU requirements and also means the
> hash table will be on node 0.
>
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
> arch/powerpc/mm/hash_utils_64.c | 12 +++++++++---
> 1 files changed, 9 insertions(+), 3 deletions(-)
>
> diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
> index 9326a69..487c5e2 100644
> --- a/arch/powerpc/mm/hash_utils_64.c
> +++ b/arch/powerpc/mm/hash_utils_64.c
> @@ -471,7 +471,7 @@ void __init htab_initialize(void)
> unsigned long table;
> unsigned long pteg_count;
> unsigned long mode_rw;
> - unsigned long base = 0, size = 0;
> + unsigned long base = 0, size = 0, limit;
> int i;
>
> extern unsigned long tce_alloc_start, tce_alloc_end;
> @@ -505,9 +505,15 @@ void __init htab_initialize(void)
> _SDR1 = 0;
> } else {
> /* Find storage for the HPT. Must be contiguous in
> - * the absolute address space.
> + * the absolute address space. On cell we want it to be
> + * in the first 1 Gig.
> */
> - table = lmb_alloc(htab_size_bytes, htab_size_bytes);
> + if (machine_is(cell))
> + limit = 0x40000000;
> + else
> + limit = 0;
> +
> + table = lmb_alloc_base(htab_size_bytes, htab_size_bytes, limit);
>
> DBG("Hash table allocated at %lx, size: %lx\n", table,
> htab_size_bytes);
^ permalink raw reply
* Re: [PATCH 1/3] Add set_dma_ops() to match get_dma_ops().
From: Benjamin Herrenschmidt @ 2008-02-05 0:23 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, cbe-oss-dev
In-Reply-To: <edf2d9650b044e2bc21e9b74ad1044f4e5b6615c.1201257905.git.michael@ellerman.id.au>
On Fri, 2008-01-25 at 21:45 +1100, Michael Ellerman wrote:
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
> include/asm-powerpc/dma-mapping.h | 5 +++++
> 1 files changed, 5 insertions(+), 0 deletions(-)
>
> diff --git a/include/asm-powerpc/dma-mapping.h b/include/asm-powerpc/dma-mapping.h
> index 5eea6db..bbefb69 100644
> --- a/include/asm-powerpc/dma-mapping.h
> +++ b/include/asm-powerpc/dma-mapping.h
> @@ -76,6 +76,11 @@ static inline struct dma_mapping_ops *get_dma_ops(struct device *dev)
> return dev->archdata.dma_ops;
> }
>
> +static inline void set_dma_ops(struct device *dev, struct dma_mapping_ops *ops)
> +{
> + dev->archdata.dma_ops = ops;
> +}
> +
> static inline int dma_supported(struct device *dev, u64 mask)
> {
> struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
^ permalink raw reply
* Re: [PATCH 3/8] Split out the logic that allocates struct iommus
From: Benjamin Herrenschmidt @ 2008-02-05 0:23 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, cbe-oss-dev
In-Reply-To: <7bef68137a3a6f5e75b0b54db4b8af8705344f42.1201616038.git.michael@ellerman.id.au>
On Wed, 2008-01-30 at 01:13 +1100, Michael Ellerman wrote:
> Split out the logic that allocates a struct iommu into a separate
> function. This can fail however the calling code has never cared - so
> just return if we can't allocate an iommu.
>
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
> arch/powerpc/platforms/cell/iommu.c | 20 ++++++++++++++++----
> 1 files changed, 16 insertions(+), 4 deletions(-)
>
> diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
> index 9223559..4f1ca43 100644
> --- a/arch/powerpc/platforms/cell/iommu.c
> +++ b/arch/powerpc/platforms/cell/iommu.c
> @@ -565,10 +565,9 @@ static int __init cell_iommu_get_window(struct device_node *np,
> return 0;
> }
>
> -static void __init cell_iommu_init_one(struct device_node *np, unsigned long offset)
> +static struct cbe_iommu * __init cell_iommu_alloc(struct device_node *np)
> {
> struct cbe_iommu *iommu;
> - unsigned long base, size;
> int nid, i;
>
> /* Get node ID */
> @@ -576,7 +575,7 @@ static void __init cell_iommu_init_one(struct device_node *np, unsigned long off
> if (nid < 0) {
> printk(KERN_ERR "iommu: failed to get node for %s\n",
> np->full_name);
> - return;
> + return NULL;
> }
> pr_debug("iommu: setting up iommu for node %d (%s)\n",
> nid, np->full_name);
> @@ -592,7 +591,7 @@ static void __init cell_iommu_init_one(struct device_node *np, unsigned long off
> if (cbe_nr_iommus >= NR_IOMMUS) {
> printk(KERN_ERR "iommu: too many IOMMUs detected ! (%s)\n",
> np->full_name);
> - return;
> + return NULL;
> }
>
> /* Init base fields */
> @@ -603,6 +602,19 @@ static void __init cell_iommu_init_one(struct device_node *np, unsigned long off
> snprintf(iommu->name, sizeof(iommu->name), "iommu%d", i);
> INIT_LIST_HEAD(&iommu->windows);
>
> + return iommu;
> +}
> +
> +static void __init cell_iommu_init_one(struct device_node *np,
> + unsigned long offset)
> +{
> + struct cbe_iommu *iommu;
> + unsigned long base, size;
> +
> + iommu = cell_iommu_alloc(np);
> + if (!iommu)
> + return;
> +
> /* Obtain a window for it */
> cell_iommu_get_window(np, &base, &size);
>
^ permalink raw reply
* Re: [PATCH 5/8] Split out the IOMMU logic from cell_dma_dev_setup()
From: Benjamin Herrenschmidt @ 2008-02-05 0:26 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, cbe-oss-dev
In-Reply-To: <b328031747602deeac6827c054b7986734a9c322.1201616038.git.michael@ellerman.id.au>
On Wed, 2008-01-30 at 01:14 +1100, Michael Ellerman wrote:
> Split the IOMMU logic out from cell_dma_dev_setup() into a separate
> function. If we're not using dma_direct_ops or dma_iommu_ops we don't
> know what the hell's going on, so BUG.
>
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
> arch/powerpc/platforms/cell/iommu.c | 19 +++++++++++++------
> 1 files changed, 13 insertions(+), 6 deletions(-)
>
> diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
> index a86e5bb..e9769fc 100644
> --- a/arch/powerpc/platforms/cell/iommu.c
> +++ b/arch/powerpc/platforms/cell/iommu.c
> @@ -507,17 +507,12 @@ static struct cbe_iommu *cell_iommu_for_node(int nid)
>
> static unsigned long cell_dma_direct_offset;
>
> -static void cell_dma_dev_setup(struct device *dev)
> +static void cell_dma_dev_setup_iommu(struct device *dev)
> {
> struct iommu_window *window;
> struct cbe_iommu *iommu;
> struct dev_archdata *archdata = &dev->archdata;
>
> - if (get_pci_dma_ops() == &dma_direct_ops) {
> - archdata->dma_data = (void *)cell_dma_direct_offset;
> - return;
> - }
> -
> /* Current implementation uses the first window available in that
> * node's iommu. We -might- do something smarter later though it may
> * never be necessary
> @@ -534,6 +529,18 @@ static void cell_dma_dev_setup(struct device *dev)
> archdata->dma_data = &window->table;
> }
>
> +static void cell_dma_dev_setup(struct device *dev)
> +{
> + struct dev_archdata *archdata = &dev->archdata;
> +
> + if (get_pci_dma_ops() == &dma_iommu_ops)
> + cell_dma_dev_setup_iommu(dev);
> + else if (get_pci_dma_ops() == &dma_direct_ops)
> + archdata->dma_data = (void *)cell_dma_direct_offset;
> + else
> + BUG();
> +}
> +
> static void cell_pci_dma_dev_setup(struct pci_dev *dev)
> {
> cell_dma_dev_setup(&dev->dev);
^ permalink raw reply
* Re: [PATCH 6/8] Add support to cell_iommu_setup_page_tables() for multiple windows
From: Benjamin Herrenschmidt @ 2008-02-05 0:26 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, cbe-oss-dev
In-Reply-To: <75f9137843ca0bcb81df8274c98a2a21777a35bf.1201616038.git.michael@ellerman.id.au>
On Wed, 2008-01-30 at 01:14 +1100, Michael Ellerman wrote:
> Add support to cell_iommu_setup_page_tables() for handling two windows,
> the dynamic window and the fixed window. A fixed window size of 0
> indicates that there is no fixed window at all.
>
> Currently there are no callers who pass a non-zero fixed window, but the
> upcoming fixed IOMMU mapping patch will change that.
>
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
> arch/powerpc/platforms/cell/iommu.c | 15 ++++++++++-----
> 1 files changed, 10 insertions(+), 5 deletions(-)
>
> diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
> index e9769fc..7779dbf 100644
> --- a/arch/powerpc/platforms/cell/iommu.c
> +++ b/arch/powerpc/platforms/cell/iommu.c
> @@ -307,14 +307,19 @@ static int cell_iommu_find_ioc(int nid, unsigned long *base)
> }
>
> static void cell_iommu_setup_page_tables(struct cbe_iommu *iommu,
> - unsigned long base, unsigned long size)
> + unsigned long dbase, unsigned long dsize,
> + unsigned long fbase, unsigned long fsize)
> {
> struct page *page;
> int i;
> unsigned long reg, segments, pages_per_segment, ptab_size, stab_size,
> - n_pte_pages;
> + n_pte_pages, base;
>
> - segments = size >> IO_SEGMENT_SHIFT;
> + base = dbase;
> + if (fsize != 0)
> + base = min(fbase, dbase);
> +
> + segments = max(dbase + dsize, fbase + fsize) >> IO_SEGMENT_SHIFT;
> pages_per_segment = 1ull << IO_PAGENO_BITS;
>
> pr_debug("%s: iommu[%d]: segments: %lu, pages per segment: %lu\n",
> @@ -366,7 +371,7 @@ static void cell_iommu_setup_page_tables(struct cbe_iommu *iommu,
> }
>
> pr_debug("Setting up IOMMU stab:\n");
> - for (i = 0; i * (1ul << IO_SEGMENT_SHIFT) < size; i++) {
> + for (i = base >> IO_SEGMENT_SHIFT; i < segments; i++) {
> iommu->stab[i] = reg |
> (__pa(iommu->ptab) + n_pte_pages * IOMMU_PAGE_SIZE * i);
> pr_debug("\t[%d] 0x%016lx\n", i, iommu->stab[i]);
> @@ -417,7 +422,7 @@ static void cell_iommu_enable_hardware(struct cbe_iommu *iommu)
> static void cell_iommu_setup_hardware(struct cbe_iommu *iommu,
> unsigned long base, unsigned long size)
> {
> - cell_iommu_setup_page_tables(iommu, base, size);
> + cell_iommu_setup_page_tables(iommu, base, size, 0, 0);
> cell_iommu_enable_hardware(iommu);
> }
>
^ permalink raw reply
* Re: [PATCH 7/8] Split out the ioid fetching/checking logic
From: Benjamin Herrenschmidt @ 2008-02-05 0:27 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, cbe-oss-dev
In-Reply-To: <aa11f5302486ba8b922828b78af1f124b38c9671.1201616038.git.michael@ellerman.id.au>
On Wed, 2008-01-30 at 01:14 +1100, Michael Ellerman wrote:
> Split out the ioid fetching and checking logic so we can use it elsewhere
> in a subsequent patch.
>
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
> arch/powerpc/platforms/cell/iommu.c | 23 +++++++++++++++++------
> 1 files changed, 17 insertions(+), 6 deletions(-)
>
> diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
> index 7779dbf..3baade1 100644
> --- a/arch/powerpc/platforms/cell/iommu.c
> +++ b/arch/powerpc/platforms/cell/iommu.c
> @@ -443,25 +443,36 @@ static struct iommu_window *find_window(struct cbe_iommu *iommu,
> }
> #endif
>
> +static inline u32 cell_iommu_get_ioid(struct device_node *np)
> +{
> + const u32 *ioid;
> +
> + ioid = of_get_property(np, "ioid", NULL);
> + if (ioid == NULL) {
> + printk(KERN_WARNING "iommu: missing ioid for %s using 0\n",
> + np->full_name);
> + return 0;
> + }
> +
> + return *ioid;
> +}
> +
> static struct iommu_window * __init
> cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np,
> unsigned long offset, unsigned long size,
> unsigned long pte_offset)
> {
> struct iommu_window *window;
> - const unsigned int *ioid;
> + u32 ioid;
>
> - ioid = of_get_property(np, "ioid", NULL);
> - if (ioid == NULL)
> - printk(KERN_WARNING "iommu: missing ioid for %s using 0\n",
> - np->full_name);
> + ioid = cell_iommu_get_ioid(np);
>
> window = kmalloc_node(sizeof(*window), GFP_KERNEL, iommu->nid);
> BUG_ON(window == NULL);
>
> window->offset = offset;
> window->size = size;
> - window->ioid = ioid ? *ioid : 0;
> + window->ioid = ioid;
> window->iommu = iommu;
> window->pte_offset = pte_offset;
>
^ permalink raw reply
* [PATCH v2] Made FSL Book-E PMC support more generic
From: Andy Fleming @ 2008-02-05 0:27 UTC (permalink / raw)
To: linuxppc-dev, galak
Some of the more recent e300 cores have the same performance monitor
implementation as the e500. e300 isn't book-e, so the name isn't
really appropriate. In preparation for e300 support, rename a bunch
of fsl_booke things to say fsl_emb (Freescale Embedded Performance Monitors).
Signed-off-by: Andy Fleming <afleming@freescale.com>
---
arch/powerpc/kernel/cputable.c | 4 +-
arch/powerpc/kernel/pmc.c | 2 +-
arch/powerpc/oprofile/Makefile | 2 +-
arch/powerpc/oprofile/common.c | 6 +-
.../{op_model_fsl_booke.c => op_model_fsl_emb.c} | 28 ++++----
arch/powerpc/platforms/Kconfig.cputype | 4 +
include/asm-powerpc/cputable.h | 2 +-
include/asm-powerpc/oprofile_impl.h | 2 +-
include/asm-powerpc/reg.h | 4 +
include/asm-powerpc/reg_booke.h | 62 -----------------
include/asm-powerpc/reg_fsl_emb.h | 72 ++++++++++++++++++++
11 files changed, 102 insertions(+), 86 deletions(-)
rename arch/powerpc/oprofile/{op_model_fsl_booke.c => op_model_fsl_emb.c} (91%)
create mode 100644 include/asm-powerpc/reg_fsl_emb.h
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index a4c2771..98a1c9e 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -1435,7 +1435,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.dcache_bsize = 32,
.num_pmcs = 4,
.oprofile_cpu_type = "ppc/e500",
- .oprofile_type = PPC_OPROFILE_BOOKE,
+ .oprofile_type = PPC_OPROFILE_FSL_EMB,
.machine_check = machine_check_e500,
.platform = "ppc8540",
},
@@ -1453,7 +1453,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.dcache_bsize = 32,
.num_pmcs = 4,
.oprofile_cpu_type = "ppc/e500",
- .oprofile_type = PPC_OPROFILE_BOOKE,
+ .oprofile_type = PPC_OPROFILE_FSL_EMB,
.machine_check = machine_check_e500,
.platform = "ppc8548",
},
diff --git a/arch/powerpc/kernel/pmc.c b/arch/powerpc/kernel/pmc.c
index ea04e0a..0516e2d 100644
--- a/arch/powerpc/kernel/pmc.c
+++ b/arch/powerpc/kernel/pmc.c
@@ -26,7 +26,7 @@
static void dummy_perf(struct pt_regs *regs)
{
-#if defined(CONFIG_FSL_BOOKE) && !defined(CONFIG_E200)
+#if defined(CONFIG_FSL_EMB_PERFMON)
mtpmr(PMRN_PMGC0, mfpmr(PMRN_PMGC0) & ~PMGC0_PMIE);
#elif defined(CONFIG_PPC64) || defined(CONFIG_6xx)
if (cur_cpu_spec->pmc_type == PPC_PMC_IBM)
diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile
index c5f64c3..2ef6b0d 100644
--- a/arch/powerpc/oprofile/Makefile
+++ b/arch/powerpc/oprofile/Makefile
@@ -15,5 +15,5 @@ oprofile-$(CONFIG_OPROFILE_CELL) += op_model_cell.o \
cell/spu_profiler.o cell/vma_map.o \
cell/spu_task_sync.o
oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o op_model_pa6t.o
-oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o
+oprofile-$(CONFIG_FSL_EMB_PERFMON) += op_model_fsl_emb.o
oprofile-$(CONFIG_6xx) += op_model_7450.o
diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c
index a28cce1..4908dc9 100644
--- a/arch/powerpc/oprofile/common.c
+++ b/arch/powerpc/oprofile/common.c
@@ -202,9 +202,9 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
model = &op_model_7450;
break;
#endif
-#ifdef CONFIG_FSL_BOOKE
- case PPC_OPROFILE_BOOKE:
- model = &op_model_fsl_booke;
+#if defined(CONFIG_FSL_EMB_PERFMON)
+ case PPC_OPROFILE_FSL_EMB:
+ model = &op_model_fsl_emb;
break;
#endif
default:
diff --git a/arch/powerpc/oprofile/op_model_fsl_booke.c b/arch/powerpc/oprofile/op_model_fsl_emb.c
similarity index 91%
rename from arch/powerpc/oprofile/op_model_fsl_booke.c
rename to arch/powerpc/oprofile/op_model_fsl_emb.c
index 183a28b..91596f6 100644
--- a/arch/powerpc/oprofile/op_model_fsl_booke.c
+++ b/arch/powerpc/oprofile/op_model_fsl_emb.c
@@ -1,7 +1,5 @@
/*
- * arch/powerpc/oprofile/op_model_fsl_booke.c
- *
- * Freescale Book-E oprofile support, based on ppc64 oprofile support
+ * Freescale Embedded oprofile support, based on ppc64 oprofile support
* Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
*
* Copyright (c) 2004 Freescale Semiconductor, Inc
@@ -22,7 +20,7 @@
#include <asm/system.h>
#include <asm/processor.h>
#include <asm/cputable.h>
-#include <asm/reg_booke.h>
+#include <asm/reg_fsl_emb.h>
#include <asm/page.h>
#include <asm/pmc.h>
#include <asm/oprofile_impl.h>
@@ -244,7 +242,7 @@ static void dump_pmcs(void)
mfpmr(PMRN_PMLCA3), mfpmr(PMRN_PMLCB3));
}
-static int fsl_booke_cpu_setup(struct op_counter_config *ctr)
+static int fsl_emb_cpu_setup(struct op_counter_config *ctr)
{
int i;
@@ -262,7 +260,7 @@ static int fsl_booke_cpu_setup(struct op_counter_config *ctr)
return 0;
}
-static int fsl_booke_reg_setup(struct op_counter_config *ctr,
+static int fsl_emb_reg_setup(struct op_counter_config *ctr,
struct op_system_config *sys,
int num_ctrs)
{
@@ -281,7 +279,7 @@ static int fsl_booke_reg_setup(struct op_counter_config *ctr,
return 0;
}
-static int fsl_booke_start(struct op_counter_config *ctr)
+static int fsl_emb_start(struct op_counter_config *ctr)
{
int i;
@@ -315,7 +313,7 @@ static int fsl_booke_start(struct op_counter_config *ctr)
return 0;
}
-static void fsl_booke_stop(void)
+static void fsl_emb_stop(void)
{
/* freeze counters */
pmc_stop_ctrs();
@@ -329,7 +327,7 @@ static void fsl_booke_stop(void)
}
-static void fsl_booke_handle_interrupt(struct pt_regs *regs,
+static void fsl_emb_handle_interrupt(struct pt_regs *regs,
struct op_counter_config *ctr)
{
unsigned long pc;
@@ -362,10 +360,10 @@ static void fsl_booke_handle_interrupt(struct pt_regs *regs,
pmc_start_ctrs(1);
}
-struct op_powerpc_model op_model_fsl_booke = {
- .reg_setup = fsl_booke_reg_setup,
- .cpu_setup = fsl_booke_cpu_setup,
- .start = fsl_booke_start,
- .stop = fsl_booke_stop,
- .handle_interrupt = fsl_booke_handle_interrupt,
+struct op_powerpc_model op_model_fsl_emb = {
+ .reg_setup = fsl_emb_reg_setup,
+ .cpu_setup = fsl_emb_cpu_setup,
+ .start = fsl_emb_start,
+ .stop = fsl_emb_stop,
+ .handle_interrupt = fsl_emb_handle_interrupt,
};
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 7fc4110..eea2e70 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -94,6 +94,7 @@ config 8xx
bool
config E500
+ select FSL_EMB_PERFMON
bool
config PPC_FPU
@@ -115,6 +116,9 @@ config FSL_BOOKE
depends on E200 || E500
default y
+config FSL_EMB_PERFMON
+ bool
+
config PTE_64BIT
bool
depends on 44x || E500
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index 528ef18..1e79673 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -46,7 +46,7 @@ enum powerpc_oprofile_type {
PPC_OPROFILE_RS64 = 1,
PPC_OPROFILE_POWER4 = 2,
PPC_OPROFILE_G4 = 3,
- PPC_OPROFILE_BOOKE = 4,
+ PPC_OPROFILE_FSL_EMB = 4,
PPC_OPROFILE_CELL = 5,
PPC_OPROFILE_PA6T = 6,
};
diff --git a/include/asm-powerpc/oprofile_impl.h b/include/asm-powerpc/oprofile_impl.h
index 938fefb..95035c6 100644
--- a/include/asm-powerpc/oprofile_impl.h
+++ b/include/asm-powerpc/oprofile_impl.h
@@ -54,7 +54,7 @@ struct op_powerpc_model {
int num_counters;
};
-extern struct op_powerpc_model op_model_fsl_booke;
+extern struct op_powerpc_model op_model_fsl_emb;
extern struct op_powerpc_model op_model_rs64;
extern struct op_powerpc_model op_model_power4;
extern struct op_powerpc_model op_model_7450;
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h
index 2408a29..0d62389 100644
--- a/include/asm-powerpc/reg.h
+++ b/include/asm-powerpc/reg.h
@@ -18,6 +18,10 @@
#include <asm/reg_booke.h>
#endif /* CONFIG_BOOKE || CONFIG_40x */
+#ifdef CONFIG_FSL_EMB_PERFMON
+#include <asm/reg_fsl_emb.h>
+#endif
+
#ifdef CONFIG_8xx
#include <asm/reg_8xx.h>
#endif /* CONFIG_8xx */
diff --git a/include/asm-powerpc/reg_booke.h b/include/asm-powerpc/reg_booke.h
index 0405ef4..cf54a3f 100644
--- a/include/asm-powerpc/reg_booke.h
+++ b/include/asm-powerpc/reg_booke.h
@@ -9,68 +9,6 @@
#ifndef __ASM_POWERPC_REG_BOOKE_H__
#define __ASM_POWERPC_REG_BOOKE_H__
-#ifndef __ASSEMBLY__
-/* Performance Monitor Registers */
-#define mfpmr(rn) ({unsigned int rval; \
- asm volatile("mfpmr %0," __stringify(rn) \
- : "=r" (rval)); rval;})
-#define mtpmr(rn, v) asm volatile("mtpmr " __stringify(rn) ",%0" : : "r" (v))
-#endif /* __ASSEMBLY__ */
-
-/* Freescale Book E Performance Monitor APU Registers */
-#define PMRN_PMC0 0x010 /* Performance Monitor Counter 0 */
-#define PMRN_PMC1 0x011 /* Performance Monitor Counter 1 */
-#define PMRN_PMC2 0x012 /* Performance Monitor Counter 1 */
-#define PMRN_PMC3 0x013 /* Performance Monitor Counter 1 */
-#define PMRN_PMLCA0 0x090 /* PM Local Control A0 */
-#define PMRN_PMLCA1 0x091 /* PM Local Control A1 */
-#define PMRN_PMLCA2 0x092 /* PM Local Control A2 */
-#define PMRN_PMLCA3 0x093 /* PM Local Control A3 */
-
-#define PMLCA_FC 0x80000000 /* Freeze Counter */
-#define PMLCA_FCS 0x40000000 /* Freeze in Supervisor */
-#define PMLCA_FCU 0x20000000 /* Freeze in User */
-#define PMLCA_FCM1 0x10000000 /* Freeze when PMM==1 */
-#define PMLCA_FCM0 0x08000000 /* Freeze when PMM==0 */
-#define PMLCA_CE 0x04000000 /* Condition Enable */
-
-#define PMLCA_EVENT_MASK 0x007f0000 /* Event field */
-#define PMLCA_EVENT_SHIFT 16
-
-#define PMRN_PMLCB0 0x110 /* PM Local Control B0 */
-#define PMRN_PMLCB1 0x111 /* PM Local Control B1 */
-#define PMRN_PMLCB2 0x112 /* PM Local Control B2 */
-#define PMRN_PMLCB3 0x113 /* PM Local Control B3 */
-
-#define PMLCB_THRESHMUL_MASK 0x0700 /* Threshhold Multiple Field */
-#define PMLCB_THRESHMUL_SHIFT 8
-
-#define PMLCB_THRESHOLD_MASK 0x003f /* Threshold Field */
-#define PMLCB_THRESHOLD_SHIFT 0
-
-#define PMRN_PMGC0 0x190 /* PM Global Control 0 */
-
-#define PMGC0_FAC 0x80000000 /* Freeze all Counters */
-#define PMGC0_PMIE 0x40000000 /* Interrupt Enable */
-#define PMGC0_FCECE 0x20000000 /* Freeze countes on
- Enabled Condition or
- Event */
-
-#define PMRN_UPMC0 0x000 /* User Performance Monitor Counter 0 */
-#define PMRN_UPMC1 0x001 /* User Performance Monitor Counter 1 */
-#define PMRN_UPMC2 0x002 /* User Performance Monitor Counter 1 */
-#define PMRN_UPMC3 0x003 /* User Performance Monitor Counter 1 */
-#define PMRN_UPMLCA0 0x080 /* User PM Local Control A0 */
-#define PMRN_UPMLCA1 0x081 /* User PM Local Control A1 */
-#define PMRN_UPMLCA2 0x082 /* User PM Local Control A2 */
-#define PMRN_UPMLCA3 0x083 /* User PM Local Control A3 */
-#define PMRN_UPMLCB0 0x100 /* User PM Local Control B0 */
-#define PMRN_UPMLCB1 0x101 /* User PM Local Control B1 */
-#define PMRN_UPMLCB2 0x102 /* User PM Local Control B2 */
-#define PMRN_UPMLCB3 0x103 /* User PM Local Control B3 */
-#define PMRN_UPMGC0 0x180 /* User PM Global Control 0 */
-
-
/* Machine State Register (MSR) Fields */
#define MSR_UCLE (1<<26) /* User-mode cache lock enable */
#define MSR_SPE (1<<25) /* Enable SPE */
diff --git a/include/asm-powerpc/reg_fsl_emb.h b/include/asm-powerpc/reg_fsl_emb.h
new file mode 100644
index 0000000..1e180a5
--- /dev/null
+++ b/include/asm-powerpc/reg_fsl_emb.h
@@ -0,0 +1,72 @@
+/*
+ * Contains register definitions for the Freescale Embedded Performance
+ * Monitor.
+ */
+#ifdef __KERNEL__
+#ifndef __ASM_POWERPC_REG_FSL_EMB_H__
+#define __ASM_POWERPC_REG_FSL_EMB_H__
+
+#ifndef __ASSEMBLY__
+/* Performance Monitor Registers */
+#define mfpmr(rn) ({unsigned int rval; \
+ asm volatile("mfpmr %0," __stringify(rn) \
+ : "=r" (rval)); rval;})
+#define mtpmr(rn, v) asm volatile("mtpmr " __stringify(rn) ",%0" : : "r" (v))
+#endif /* __ASSEMBLY__ */
+
+/* Freescale Book E Performance Monitor APU Registers */
+#define PMRN_PMC0 0x010 /* Performance Monitor Counter 0 */
+#define PMRN_PMC1 0x011 /* Performance Monitor Counter 1 */
+#define PMRN_PMC2 0x012 /* Performance Monitor Counter 1 */
+#define PMRN_PMC3 0x013 /* Performance Monitor Counter 1 */
+#define PMRN_PMLCA0 0x090 /* PM Local Control A0 */
+#define PMRN_PMLCA1 0x091 /* PM Local Control A1 */
+#define PMRN_PMLCA2 0x092 /* PM Local Control A2 */
+#define PMRN_PMLCA3 0x093 /* PM Local Control A3 */
+
+#define PMLCA_FC 0x80000000 /* Freeze Counter */
+#define PMLCA_FCS 0x40000000 /* Freeze in Supervisor */
+#define PMLCA_FCU 0x20000000 /* Freeze in User */
+#define PMLCA_FCM1 0x10000000 /* Freeze when PMM==1 */
+#define PMLCA_FCM0 0x08000000 /* Freeze when PMM==0 */
+#define PMLCA_CE 0x04000000 /* Condition Enable */
+
+#define PMLCA_EVENT_MASK 0x007f0000 /* Event field */
+#define PMLCA_EVENT_SHIFT 16
+
+#define PMRN_PMLCB0 0x110 /* PM Local Control B0 */
+#define PMRN_PMLCB1 0x111 /* PM Local Control B1 */
+#define PMRN_PMLCB2 0x112 /* PM Local Control B2 */
+#define PMRN_PMLCB3 0x113 /* PM Local Control B3 */
+
+#define PMLCB_THRESHMUL_MASK 0x0700 /* Threshhold Multiple Field */
+#define PMLCB_THRESHMUL_SHIFT 8
+
+#define PMLCB_THRESHOLD_MASK 0x003f /* Threshold Field */
+#define PMLCB_THRESHOLD_SHIFT 0
+
+#define PMRN_PMGC0 0x190 /* PM Global Control 0 */
+
+#define PMGC0_FAC 0x80000000 /* Freeze all Counters */
+#define PMGC0_PMIE 0x40000000 /* Interrupt Enable */
+#define PMGC0_FCECE 0x20000000 /* Freeze countes on
+ Enabled Condition or
+ Event */
+
+#define PMRN_UPMC0 0x000 /* User Performance Monitor Counter 0 */
+#define PMRN_UPMC1 0x001 /* User Performance Monitor Counter 1 */
+#define PMRN_UPMC2 0x002 /* User Performance Monitor Counter 1 */
+#define PMRN_UPMC3 0x003 /* User Performance Monitor Counter 1 */
+#define PMRN_UPMLCA0 0x080 /* User PM Local Control A0 */
+#define PMRN_UPMLCA1 0x081 /* User PM Local Control A1 */
+#define PMRN_UPMLCA2 0x082 /* User PM Local Control A2 */
+#define PMRN_UPMLCA3 0x083 /* User PM Local Control A3 */
+#define PMRN_UPMLCB0 0x100 /* User PM Local Control B0 */
+#define PMRN_UPMLCB1 0x101 /* User PM Local Control B1 */
+#define PMRN_UPMLCB2 0x102 /* User PM Local Control B2 */
+#define PMRN_UPMLCB3 0x103 /* User PM Local Control B3 */
+#define PMRN_UPMGC0 0x180 /* User PM Global Control 0 */
+
+
+#endif /* __ASM_POWERPC_REG_FSL_EMB_H__ */
+#endif /* __KERNEL__ */
--
1.5.0.2.230.gfbe3d-dirty
^ permalink raw reply related
* [PATCH v2] Add oprofile support for e300
From: Andy Fleming @ 2008-02-05 0:28 UTC (permalink / raw)
To: linuxppc-dev, galak
The e300 c3 and c4 variants support hardware performance monitor counters which
are identical to those found in the e500.
Signed-off-by: Andy Fleming <afleming@freescale.com>
---
arch/powerpc/kernel/cputable.c | 6 ++++++
arch/powerpc/platforms/Kconfig | 1 +
2 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 98a1c9e..2a8f5cc 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -959,6 +959,9 @@ static struct cpu_spec __initdata cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_603,
+ .num_pmcs = 4,
+ .oprofile_cpu_type = "ppc/e300",
+ .oprofile_type = PPC_OPROFILE_FSL_EMB,
.platform = "ppc603",
},
{ /* e300c4 (e300c1, plus one IU) */
@@ -971,6 +974,9 @@ static struct cpu_spec __initdata cpu_specs[] = {
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_603,
.machine_check = machine_check_generic,
+ .num_pmcs = 4,
+ .oprofile_cpu_type = "ppc/e300",
+ .oprofile_type = PPC_OPROFILE_FSL_EMB,
.platform = "ppc603",
},
{ /* default match, we assume split I/D cache & TB (non-601)... */
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index fdce10c..045b8c8 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -24,6 +24,7 @@ config PPC_83xx
select MPC83xx
select IPIC
select WANT_DEVICE_TREE
+ select FSL_EMB_PERFMON
config PPC_86xx
bool "Freescale 86xx"
--
1.5.0.2.230.gfbe3d-dirty
^ permalink raw reply related
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