* Re: Interpreting /proc/meminfo. How much free memory do I have?
From: Roger Larsson @ 2006-03-27 7:53 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <20060327064907.23992.qmail@mx1.aruba.it>
On m=E5ndag 27 mars 2006 08.49, antonio.dibacco wrote:
> Hi,
>
> I'm a little bit puzzled with the fields in /proc/meminfo. Which fields
> have I to sum up to get the amount of free memory?
=46rom a 2.6 /proc/meminfo
MemTotal: 515532 kB
MemFree: 6012 kB
Buffers: 79964 kB
Cached: 83264 kB
SwapCached: 82840 kB
Active: 294024 kB
Inactive: 130304 kB
=2D - -
Completely free is only MemFree. But those pages are only needed for
interrupt handlers (close enough).
Cached pages are also free but since they contain data that maybe will
be needed again (unmodified data that already is on disk) they are not
returned to MemFree state.
Inactive pages has not been in use for awhile and can be written out
if needed (some are probably unmodified and quick to get)
/RogerL
^ permalink raw reply
* Re: Memory mapping PCI memory region to user space
From: Phil Nitschke @ 2006-03-27 8:02 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-embedded
In-Reply-To: <204E7000-3E88-4497-86C0-5AF786D72F75@kernel.crashing.org>
On Thu, 2006-03-23 at 09:44 -0600, Kumar Gala wrote:
> On Mar 23, 2006, at 8:21 AM, Wyse, Chris wrote:
>
> > Hi,
> >
> > I'm trying to map a PCI memory region 1 into user space from my
> > driver (PPC440GX, Linux 2.6.10). Here's the mmap routine of the
> > driver that I'm using:
>
> Why don't use the mmap file exposed by sysfs so you dont have to
> write your own code?
>
> See Documentation/filesystems/sysfs-pci.txt. But effectively down
> under /sys/bus/pci/devices/[domain:bus:dev:func]/ you will get
> resource[0..N-1] that corresponds to each BAR on the device. This is
> a mmap file to access that region.
I have some custom hardware that appears on the PCI bus as follows:
bash-3.00# lspci -vv
00:01.0 Class 0680: 1172:0004 (rev 01)
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr-
Stepping- SERR- FastB2B-
Status: Cap- 66Mhz+ UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort+
<TAbort- <MAbort- >SERR- <PERR-
Latency: 128, Cache Line Size 08
Interrupt: pin A routed to IRQ 71
Region 0: Memory at 000000009ffff000 (32-bit, non-prefetchable)
[size=4K]
Region 1: Memory at 000000009fc00000 (32-bit, non-prefetchable)
[size=2M]
But when I try to access resource0 or resource1, I get a read error.
What characteristic of the device or driver determines whether it will
allow mmap-ing?
(I've written the driver for this device myself.)
--
Phil
^ permalink raw reply
* Interpreting /proc/meminfo. How much free memory do I have?
From: antonio.dibacco @ 2006-03-27 6:49 UTC (permalink / raw)
To: linuxppc-embedded
Hi,
I'm a little bit puzzled with the fields in /proc/meminfo. Which fields have
I to sum up to get the amount of free memory?
Thank you,
Antonio.
^ permalink raw reply
* Re: [PATCH 0/4] MPC52xx updates : lite5200b + ide support
From: Sylvain Munaut @ 2006-03-27 6:16 UTC (permalink / raw)
To: Paul Mackerras; +Cc: Linux PPC embedded
In-Reply-To: <17447.5060.59058.187721@cargo.ozlabs.ibm.com>
Paul Mackerras wrote:
> Sylvain Munaut writes:
>
>
>> This set of updates mainly adds support for the new lite5200B
>> devboard from Freescale and support for IDE.
>>
>> Theses have been posted on the ppc-embedded mailing list some
>> time ago, they've been tested and reported working by a few people,
>> so Paul it'd be nice to get those merged upstream. If you were
>> not the one to cc about this, let me know, I'll forward those
>> to Andrew.
>>
>
> I'll handle patches 1-3, but you will need to send the IDE patch to
> the IDE maintainer, Bartlomiej Zolnierkiewicz
> <B.Zolnierkiewicz@elka.pw.edu.pl>.
>
> Paul.
>
Ok, thanks, I'll do that.
Sylvain
^ permalink raw reply
* Re: [PATCH] kdump: Fix for machine checkstop on DMA fault
From: Michael Ellerman @ 2006-03-27 5:04 UTC (permalink / raw)
To: Olof Johansson, Haren Myneni
Cc: linuxppc-dev, Paul Mackerras, Milton Miller, Olaf Hering
In-Reply-To: <20060323201258.GA5538@pb15.lixom.net>
[-- Attachment #1: Type: text/plain, Size: 1803 bytes --]
On Thu, 2006-03-23 at 14:12 -0600, Olof Johansson wrote:
> On Thu, Mar 23, 2006 at 12:19:04AM -0600, Olof Johansson wrote:
>
> > The crash kernel needs to be even more careful, and instead read out
> > the entries that are mapped and reserve them. This would require a bit
> > more plumbing since there's no way to read an entry right now, but it'd
> > remove that hole.
>
> Actually, what's probably easier is to allocate some entries when the
> purgatory is set up, and make the crash kernel only use those by modifying
> the device tree accordingly. Sort of how regular memory is handled right
> now. That'd be a cleaner solution with less changes needed.
>
> The trick will be to get a decent size contiguous allocation, but the
> same applies for the memory reserve.
I disagree. In most cases the kdump kernel will be loaded by the boot
scripts, so reserving TCE space then is ~= reserving it for the life of
the first kernel. Given that TCE space is a scarce commodity I don't
think reserving it in the first kernel is a viable option.
What we should do is modify the second kernel so that instead of
clearing the TCE tables it instead walks the tables and detects existing
mappings, and then marks those as reserved so they're not overwritten.
This should give us 100% safety from the second kernel reusing a mapping
and copping a rogue DMA, and doesn't inflict any penalty on the first
kernel. It does fall down if there's no TCE space left for a device when
the second kernel comes up, but I think that's the best trade off.
cheers
--
Michael Ellerman
IBM OzLabs
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: [BULK] Re: "transmit timed out" on FCC in MPC8260 as well as MPC8247
From: Siju Viswanath K E @ 2006-03-27 4:34 UTC (permalink / raw)
To: Wolfgang Denk; +Cc: linuxppc-embedded
In-Reply-To: <20060325001014.678AA353B50@atlas.denx.de>
On Sat, 2006-03-25 at 05:40, Wolfgang Denk wrote:
> In message <1143193658.22246.20.camel@Blaze> you wrote:
> >
> > the issue. My repository is patched upto
> > "Patch by Wojciech Kromer, 06 Jan 2004" and later changes are only
> > adding extra board support.
>
> This is definitely *not* correct. A *long* list of bugs have been
> fixed in the last two years.
I meant it only regarding the timeout issue for FCC. I was not talking
about the repository in general.
regards,
Siju
^ permalink raw reply
* Re: [BULK] Re: "transmit timed out" on FCC in MPC8260 => bug corrected
From: Siju Viswanath K E @ 2006-03-27 4:31 UTC (permalink / raw)
To: hubert.loewenguth; +Cc: Hunter, David, linuxppc-embedded
In-Reply-To: <4423DB92.5070305@thales-bm.com>
Thanks for the patch.. I have implemented the changes but since it is
not very frequent in my case, I dont know whether it works for me yet.
regards,
siju
On Fri, 2006-03-24 at 17:14, hubert.loewenguth wrote:
> Hi to the community.
>
> I'm the man who has posted numerous questions about this problem of
> fcc_enet timeout in ppc8260.
> I just want to say that the 2.6 kernel doesn't solve the problem if
> you have it on your board (I tried it, normally I have a 2.4-20 linux
> too).
> I have search for this bug during a long time, and fortunatly, I 'm
> happy to say you that finally, it is corrected since few days.
> Special thanks to "Hunter, David" for having take in consideration my
> problem, and proposing me some way of invastigations in this thread:
>
> http://ozlabs.org/pipermail/linuxppc-embedded/2006-January/021842.html
>
> In fact the solution comes from the new "MPC8260 PowerQUICC II Family
> Reference Manual" fresescale has delivered 01/19/2006.
> http://www.freescale.com/files/product/doc/MPC8260UM.pdf
^ permalink raw reply
* Re: [patch 01/13] powerpc: hvc_console updates
From: Paul Mackerras @ 2006-03-27 4:00 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: Arnd Bergmann, linuxppc-dev, cbe-oss-dev, linux-kernel
In-Reply-To: <20060323203520.909999000@dyn-9-152-242-103.boeblingen.de.ibm.com>
Arnd Bergmann writes:
> Also shuffle around some data-type declarations and moves some
> functions out of include/asm-ppc64/hvconsole.h and into a new
> drivers/char/hvc_console.h file.
Unfortunately this causes compile failures because the declarations of
hvc_instantiate and hvc_alloc in include/asm-powerpc/hvconsole.h now
don't have the definition of struct hv_ops available to them. I'll
ignore your 1/13 and 2/13 patches for now - please send fixed
versions.
Paul.
^ permalink raw reply
* [PATCH 2/2] powerpc: Cope with duplicate node & property names in /proc/device-tree
From: Michael Ellerman @ 2006-03-27 3:26 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <1143429985.443737.375094420785.qpush@concordia>
Various dodgy firmware might give us nodes and/or properties in the device
tree with conflicting names. That's generally ok, except for when we export
the device tree via /proc, so check when we're creating the proc device tree
and munge names accordingly.
Tested on a faked device tree with kexec, would be good if someone with
actual bogus firmware could try it, but just for completeness.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
fs/proc/proc_devtree.c | 103 ++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 80 insertions(+), 23 deletions(-)
Index: to-merge/fs/proc/proc_devtree.c
===================================================================
--- to-merge.orig/fs/proc/proc_devtree.c
+++ to-merge/fs/proc/proc_devtree.c
@@ -52,7 +52,8 @@ static int property_read_proc(char *page
* Add a property to a node
*/
static struct proc_dir_entry *
-__proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp)
+__proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp,
+ const char *name)
{
struct proc_dir_entry *ent;
@@ -60,14 +61,14 @@ __proc_device_tree_add_prop(struct proc_
* Unfortunately proc_register puts each new entry
* at the beginning of the list. So we rearrange them.
*/
- ent = create_proc_read_entry(pp->name,
- strncmp(pp->name, "security-", 9)
+ ent = create_proc_read_entry(name,
+ strncmp(name, "security-", 9)
? S_IRUGO : S_IRUSR, de,
property_read_proc, pp);
if (ent == NULL)
return NULL;
- if (!strncmp(pp->name, "security-", 9))
+ if (!strncmp(name, "security-", 9))
ent->size = 0; /* don't leak number of password chars */
else
ent->size = pp->length;
@@ -78,7 +79,7 @@ __proc_device_tree_add_prop(struct proc_
void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop)
{
- __proc_device_tree_add_prop(pde, prop);
+ __proc_device_tree_add_prop(pde, prop, prop->name);
}
void proc_device_tree_remove_prop(struct proc_dir_entry *pde,
@@ -106,6 +107,69 @@ void proc_device_tree_update_prop(struct
}
/*
+ * Various dodgy firmware might give us nodes and/or properties with
+ * conflicting names. That's generally ok, except for exporting via /proc,
+ * so munge names here to ensure they're unique.
+ */
+
+static int duplicate_name(struct proc_dir_entry *de, const char *name)
+{
+ struct proc_dir_entry *ent;
+ int found = 0;
+
+ spin_lock(&proc_subdir_lock);
+
+ for (ent = de->subdir; ent != NULL; ent = ent->next) {
+ if (strcmp(ent->name, name) == 0) {
+ found = 1;
+ break;
+ }
+ }
+
+ spin_unlock(&proc_subdir_lock);
+
+ return found;
+}
+
+static const char *fixup_name(struct device_node *np, struct proc_dir_entry *de,
+ const char *name)
+{
+ char *fixed_name;
+ int fixup_len = strlen(name) + 2 + 1; /* name + #x + \0 */
+ int i = 1, size;
+
+realloc:
+ fixed_name = kmalloc(fixup_len, GFP_KERNEL);
+ if (fixed_name == NULL) {
+ printk(KERN_ERR "device-tree: Out of memory trying to fixup "
+ "name \"%s\"\n", name);
+ return name;
+ }
+
+retry:
+ size = snprintf(fixed_name, fixup_len, "%s#%d", name, i);
+ size++; /* account for NULL */
+
+ if (size > fixup_len) {
+ /* We ran out of space, free and reallocate. */
+ kfree(fixed_name);
+ fixup_len = size;
+ goto realloc;
+ }
+
+ if (duplicate_name(de, fixed_name)) {
+ /* Multiple duplicates. Retry with a different offset. */
+ i++;
+ goto retry;
+ }
+
+ printk(KERN_WARNING "device-tree: Duplicate name in %s, "
+ "renamed to \"%s\"\n", np->full_name, fixed_name);
+
+ return fixed_name;
+}
+
+/*
* Process a node, adding entries for its children and its properties.
*/
void proc_device_tree_add_node(struct device_node *np,
@@ -118,37 +182,30 @@ void proc_device_tree_add_node(struct de
set_node_proc_entry(np, de);
for (child = NULL; (child = of_get_next_child(np, child));) {
+ /* Use everything after the last slash, or the full name */
p = strrchr(child->full_name, '/');
if (!p)
p = child->full_name;
else
++p;
+
+ if (duplicate_name(de, p))
+ p = fixup_name(np, de, p);
+
ent = proc_mkdir(p, de);
if (ent == 0)
break;
proc_device_tree_add_node(child, ent);
}
of_node_put(child);
+
for (pp = np->properties; pp != 0; pp = pp->next) {
- /*
- * Yet another Apple device-tree bogosity: on some machines,
- * they have properties & nodes with the same name. Those
- * properties are quite unimportant for us though, thus we
- * simply "skip" them here, but we do have to check.
- */
- spin_lock(&proc_subdir_lock);
- for (ent = de->subdir; ent != NULL; ent = ent->next)
- if (!strcmp(ent->name, pp->name))
- break;
- spin_unlock(&proc_subdir_lock);
- if (ent != NULL) {
- printk(KERN_WARNING "device-tree: property \"%s\" name"
- " conflicts with node in %s\n", pp->name,
- np->full_name);
- continue;
- }
+ p = pp->name;
+
+ if (duplicate_name(de, p))
+ p = fixup_name(np, de, p);
- ent = __proc_device_tree_add_prop(de, pp);
+ ent = __proc_device_tree_add_prop(de, pp, p);
if (ent == 0)
break;
}
^ permalink raw reply
* [PATCH 1/2] powerpc: Rename and export ppc64_firmware_features
From: Michael Ellerman @ 2006-03-27 3:26 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
We need to export ppc64_firmware_features for modules. Before we do that
I think we should probably rename it to powerpc_firmware_features.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/kernel/firmware.c | 4 +++-
arch/powerpc/platforms/iseries/setup.c | 4 ++--
arch/powerpc/platforms/pseries/firmware.c | 2 +-
arch/powerpc/platforms/pseries/setup.c | 2 +-
include/asm-powerpc/firmware.h | 4 ++--
5 files changed, 9 insertions(+), 7 deletions(-)
Index: to-merge/arch/powerpc/kernel/firmware.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/firmware.c
+++ to-merge/arch/powerpc/kernel/firmware.c
@@ -14,7 +14,9 @@
*/
#include <linux/config.h>
+#include <linux/module.h>
#include <asm/firmware.h>
-unsigned long ppc64_firmware_features;
+unsigned long powerpc_firmware_features;
+EXPORT_SYMBOL_GPL(powerpc_firmware_features);
Index: to-merge/arch/powerpc/platforms/iseries/setup.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/iseries/setup.c
+++ to-merge/arch/powerpc/platforms/iseries/setup.c
@@ -680,8 +680,8 @@ static int __init iseries_probe(int plat
if (PLATFORM_ISERIES_LPAR != platform)
return 0;
- ppc64_firmware_features |= FW_FEATURE_ISERIES;
- ppc64_firmware_features |= FW_FEATURE_LPAR;
+ powerpc_firmware_features |= FW_FEATURE_ISERIES;
+ powerpc_firmware_features |= FW_FEATURE_LPAR;
return 1;
}
Index: to-merge/arch/powerpc/platforms/pseries/firmware.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/pseries/firmware.c
+++ to-merge/arch/powerpc/platforms/pseries/firmware.c
@@ -91,7 +91,7 @@ void __init fw_feature_init(void)
continue;
/* we have a match */
- ppc64_firmware_features |=
+ powerpc_firmware_features |=
firmware_features_table[i].val;
break;
}
Index: to-merge/arch/powerpc/platforms/pseries/setup.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/pseries/setup.c
+++ to-merge/arch/powerpc/platforms/pseries/setup.c
@@ -386,7 +386,7 @@ static int __init pSeries_probe(int plat
*/
if (platform == PLATFORM_PSERIES_LPAR)
- ppc64_firmware_features |= FW_FEATURE_LPAR;
+ powerpc_firmware_features |= FW_FEATURE_LPAR;
return 1;
}
Index: to-merge/include/asm-powerpc/firmware.h
===================================================================
--- to-merge.orig/include/asm-powerpc/firmware.h
+++ to-merge/include/asm-powerpc/firmware.h
@@ -82,11 +82,11 @@ enum {
/* This is used to identify firmware features which are available
* to the kernel.
*/
-extern unsigned long ppc64_firmware_features;
+extern unsigned long powerpc_firmware_features;
#define firmware_has_feature(feature) \
((FW_FEATURE_ALWAYS & (feature)) || \
- (FW_FEATURE_POSSIBLE & ppc64_firmware_features & (feature)))
+ (FW_FEATURE_POSSIBLE & powerpc_firmware_features & (feature)))
extern void system_reset_fwnmi(void);
extern void machine_check_fwnmi(void);
^ permalink raw reply
* Re: make install on ppc
From: Brent Cook @ 2006-03-27 1:56 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <OF06763F9B.91995CDB-ON4825713E.000850DE-4825713E.000949FE@cn.ibm.com>
On Sunday 26 March 2006 19:42, Jin Qi Huang wrote:
> I also think the 'make install' is very useful, now on ia32, the 'make
> install' provided by the latest kernel linux-2.6.16 not only create
> initrd, copy vmlinuz and System.map to /boot directory, but also update
> grub, ppc32 does not provide this useful feature, maybe it is a pity!
>
Maybe narrow it to define 'make install' for new world/old world Macintoshes,
or IBM machines? I can't see a generic make install being useful for the
wider range of platforms that fall under ppc.
'make install' appears to me to be very platform dependent. Sure, on x86, you
can reasonably assume that the majority of systems have the kernel on a disk
under /boot and the bootloader is grub or lilo. I have 5 ppc machines
currently, and no two use the same bootloader or kernel image. I've seen
u-boot, yaboot, quik, powerboot (Motorola/Force), xmon (XES) and more, and
they all required different post-processing to the kernel image to boot. For
most of these, there is no way to programmatically guess where a particular
kernel image should go to work with the boot loader.
- Brent
^ permalink raw reply
* Re: [PATCH] kdump: clear and EOI IPI for kexec CPU
From: Paul Mackerras @ 2006-03-27 2:04 UTC (permalink / raw)
To: Haren Myneni; +Cc: linuxppc-dev, ellerman, Milton Miller, Olaf Hering
In-Reply-To: <44222FA0.90902@us.ibm.com>
Haren Myneni writes:
> Paul, Sorry, Please ignore the previous patch since it has one tab/space
> issue. Tested this one and kdump-dma-fault-fix.patch on P5, P4
> (non-lpar), JS21 and JS20.
>
> Thanks
> Haren
>
> Some times, the kexec CPU is not reponding to an IPI during kdump boot.
> It is causing the system in xmon. Noticed on power-4 (non-lpar). This
> patch clears and EOI IPI for kexec CPU as well before the kdump boot
> started.
Sorry, that commit message is quite opaque to me. Could you explain
in more detail what the problem is and how this fixes it?
Thanks,
Paul.
^ permalink raw reply
* Re: make install on ppc
From: Jin Qi Huang @ 2006-03-27 1:42 UTC (permalink / raw)
To: Hans Fugal; +Cc: linuxppc-dev list, linuxppc-dev-bounces+huangjq=cn.ibm.com
In-Reply-To: <44270B34.3070406@fugal.net>
[-- Attachment #1: Type: text/plain, Size: 1357 bytes --]
I also think the 'make install' is very useful, now on ia32, the 'make
install' provided by the latest kernel linux-2.6.16 not only create
initrd, copy vmlinuz and System.map to /boot directory, but also update
grub, ppc32 does not provide this useful feature, maybe it is a pity!
--
Regards,
MCP Test, Linux Technology Center, China Systems & Technology Lab
China Development Labs, Beijing Email: huangjq@cn.ibm.com
Hans Fugal <hans@fugal.net>
Sent by: linuxppc-dev-bounces+huangjq=cn.ibm.com@ozlabs.org
2006-03-27 05:44
To
Hollis Blanchard <hollis@penguinppc.org>
cc
linuxppc-dev list <linuxppc-dev@ozlabs.org>
Subject
Re: make install on ppc
Hollis Blanchard wrote:
> On Mar 21, 2006, at 8:08 AM, Hans Fugal wrote:
>
>> Is there something that stops us from having a make install target for
>> ppc?
>
> Why do you want it, and what would it do? Clearly not many people have
> needed it so far...
I bet a lot of people have typed it, wished it was there, then worked
around it. That's what I've been doing for a year now.
It doesn't do much - basically it has the proper dependencies and runs
installkernel with the appropriate arguments (as indicated by `make
help`).
Thanks
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev
[-- Attachment #2: Type: text/html, Size: 2305 bytes --]
^ permalink raw reply
* Re: [PATCH] powerpc: ibmveth: Harden driver initilisation for kexec
From: Michael Ellerman @ 2006-03-27 1:11 UTC (permalink / raw)
To: jgarzik; +Cc: linuxppc64-dev, netdev
In-Reply-To: <44074A22.8060705@us.ibm.com>
On Thu, 2006-03-02 at 13:40 -0600, Santiago Leon wrote:
> From: Michael Ellerman <michael@ellerman.id.au>
>
> After a kexec the veth driver will fail when trying to register with the
> Hypervisor because the previous kernel has not unregistered.
>
> So if the registration fails, we unregister and then try again.
>
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
> Acked-by: Anton Blanchard <anton@samba.org>
> Signed-off-by: Santiago Leon <santil@us.ibm.com>
> ---
>
> drivers/net/ibmveth.c | 32 ++++++++++++++++++++++++++------
> 1 files changed, 26 insertions(+), 6 deletions(-)
Looks like this hit the floor. Any chance of getting it into to 2.6.17
Jeff? AFAICT it should still apply cleanly.
cheers
--
Michael Ellerman
IBM OzLabs
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
^ permalink raw reply
* [PATCH] powerpc: Add oprofile calltrace support to all powerpc cpus
From: Anton Blanchard @ 2006-03-27 1:03 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
In-Reply-To: <20060327010045.GD4962@krispykreme>
Add calltrace support for other powerpc cpus. Tested on 7450.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: linux-2.6/arch/powerpc/oprofile/op_model_7450.c
===================================================================
--- linux-2.6.orig/arch/powerpc/oprofile/op_model_7450.c 2006-01-19 12:29:53.000000000 +1100
+++ linux-2.6/arch/powerpc/oprofile/op_model_7450.c 2006-03-26 23:00:02.000000000 +1100
@@ -176,13 +176,13 @@ static void fsl7450_handle_interrupt(str
mtmsr(mfmsr() | MSR_PMM);
pc = mfspr(SPRN_SIAR);
- is_kernel = (pc >= KERNELBASE);
+ is_kernel = is_kernel_addr(pc);
for (i = 0; i < NUM_CTRS; ++i) {
val = ctr_read(i);
if (val < 0) {
if (oprofile_running && ctr[i].enabled) {
- oprofile_add_pc(pc, is_kernel, i);
+ oprofile_add_ext_sample(pc, regs, i, is_kernel);
ctr_write(i, reset_value[i]);
} else {
ctr_write(i, 0);
Index: linux-2.6/arch/powerpc/oprofile/op_model_fsl_booke.c
===================================================================
--- linux-2.6.orig/arch/powerpc/oprofile/op_model_fsl_booke.c 2005-11-16 03:21:49.000000000 +1100
+++ linux-2.6/arch/powerpc/oprofile/op_model_fsl_booke.c 2006-03-26 22:58:08.000000000 +1100
@@ -154,13 +154,13 @@ static void fsl_booke_handle_interrupt(s
mtmsr(mfmsr() | MSR_PMM);
pc = regs->nip;
- is_kernel = (pc >= KERNELBASE);
+ 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_pc(pc, is_kernel, i);
+ oprofile_add_ext_sample(pc, regs, i, is_kernel);
ctr_write(i, reset_value[i]);
} else {
ctr_write(i, 0);
Index: linux-2.6/arch/powerpc/oprofile/op_model_rs64.c
===================================================================
--- linux-2.6.orig/arch/powerpc/oprofile/op_model_rs64.c 2006-01-19 12:29:53.000000000 +1100
+++ linux-2.6/arch/powerpc/oprofile/op_model_rs64.c 2006-03-26 23:01:55.000000000 +1100
@@ -175,10 +175,13 @@ static void rs64_handle_interrupt(struct
struct op_counter_config *ctr)
{
unsigned int mmcr0;
+ int is_kernel;
int val;
int i;
unsigned long pc = mfspr(SPRN_SIAR);
+ is_kernel = is_kernel_addr(pc);
+
/* set the PMM bit (see comment below) */
mtmsrd(mfmsr() | MSR_PMM);
@@ -186,7 +189,7 @@ static void rs64_handle_interrupt(struct
val = ctr_read(i);
if (val < 0) {
if (ctr[i].enabled) {
- oprofile_add_pc(pc, is_kernel_addr(pc), i);
+ oprofile_add_ext_sample(pc, regs, i, is_kernel);
ctr_write(i, reset_value[i]);
} else {
ctr_write(i, 0);
^ permalink raw reply
* [PATCH] powerpc: Remove oprofile spinlock backtrace code
From: Anton Blanchard @ 2006-03-27 1:00 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
In-Reply-To: <20060327005701.GC4962@krispykreme>
Remove oprofile spinlock backtrace code now we have proper calltrace
support. Also make MMCRA sihv and sipr bits a variable since they may
change in future cpus. Finally, MMCRA should be a 64bit quantity.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: linux-2.6/arch/powerpc/oprofile/op_model_power4.c
===================================================================
--- linux-2.6.orig/arch/powerpc/oprofile/op_model_power4.c 2006-03-26 17:55:19.000000000 +1100
+++ linux-2.6/arch/powerpc/oprofile/op_model_power4.c 2006-03-26 17:55:19.000000000 +1100
@@ -25,18 +25,14 @@ static unsigned long reset_value[OP_MAX_
static int oprofile_running;
static int mmcra_has_sihv;
+/* Unfortunately these bits vary between CPUs */
+static unsigned long mmcra_sihv = MMCRA_SIHV;
+static unsigned long mmcra_sipr = MMCRA_SIPR;
/* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */
static u32 mmcr0_val;
static u64 mmcr1_val;
-static u32 mmcra_val;
-
-/*
- * Since we do not have an NMI, backtracing through spinlocks is
- * only a best guess. In light of this, allow it to be disabled at
- * runtime.
- */
-static int backtrace_spinlocks;
+static u64 mmcra_val;
static void power4_reg_setup(struct op_counter_config *ctr,
struct op_system_config *sys,
@@ -63,8 +59,6 @@ static void power4_reg_setup(struct op_c
mmcr1_val = sys->mmcr1;
mmcra_val = sys->mmcra;
- backtrace_spinlocks = sys->backtrace_spinlocks;
-
for (i = 0; i < cur_cpu_spec->num_pmcs; ++i)
reset_value[i] = 0x80000000UL - ctr[i].count;
@@ -197,25 +191,6 @@ static void __attribute_used__ kernel_un
{
}
-static unsigned long check_spinlock_pc(struct pt_regs *regs,
- unsigned long profile_pc)
-{
- unsigned long pc = instruction_pointer(regs);
-
- /*
- * If both the SIAR (sampled instruction) and the perfmon exception
- * occurred in a spinlock region then we account the sample to the
- * calling function. This isnt 100% correct, we really need soft
- * IRQ disable so we always get the perfmon exception at the
- * point at which the SIAR is set.
- */
- if (backtrace_spinlocks && in_lock_functions(pc) &&
- in_lock_functions(profile_pc))
- return regs->link;
- else
- return profile_pc;
-}
-
/*
* On GQ and newer the MMCRA stores the HV and PR bits at the time
* the SIAR was sampled. We use that to work out if the SIAR was sampled in
@@ -228,17 +203,17 @@ static unsigned long get_pc(struct pt_re
/* Cant do much about it */
if (!mmcra_has_sihv)
- return check_spinlock_pc(regs, pc);
+ return pc;
mmcra = mfspr(SPRN_MMCRA);
/* Were we in the hypervisor? */
- if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & MMCRA_SIHV))
+ if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & mmcra_sihv))
/* function descriptor madness */
return *((unsigned long *)hypervisor_bucket);
/* We were in userspace, nothing to do */
- if (mmcra & MMCRA_SIPR)
+ if (mmcra & mmcra_sipr)
return pc;
#ifdef CONFIG_PPC_RTAS
@@ -257,7 +232,7 @@ static unsigned long get_pc(struct pt_re
/* function descriptor madness */
return *((unsigned long *)kernel_unknown_bucket);
- return check_spinlock_pc(regs, pc);
+ return pc;
}
static int get_kernel(unsigned long pc)
@@ -268,7 +243,7 @@ static int get_kernel(unsigned long pc)
is_kernel = is_kernel_addr(pc);
} else {
unsigned long mmcra = mfspr(SPRN_MMCRA);
- is_kernel = ((mmcra & MMCRA_SIPR) == 0);
+ is_kernel = ((mmcra & mmcra_sipr) == 0);
}
return is_kernel;
Index: linux-2.6/arch/powerpc/oprofile/common.c
===================================================================
--- linux-2.6.orig/arch/powerpc/oprofile/common.c 2006-03-26 17:55:19.000000000 +1100
+++ linux-2.6/arch/powerpc/oprofile/common.c 2006-03-26 17:55:19.000000000 +1100
@@ -117,17 +117,10 @@ static int op_powerpc_create_files(struc
oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel);
oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user);
-#ifdef CONFIG_PPC64
- oprofilefs_create_ulong(sb, root, "backtrace_spinlocks",
- &sys.backtrace_spinlocks);
-#endif
/* Default to tracing both kernel and user */
sys.enable_kernel = 1;
sys.enable_user = 1;
-#ifdef CONFIG_PPC64
- sys.backtrace_spinlocks = 0;
-#endif
return 0;
}
Index: linux-2.6/include/asm-powerpc/oprofile_impl.h
===================================================================
--- linux-2.6.orig/include/asm-powerpc/oprofile_impl.h 2006-03-26 17:55:19.000000000 +1100
+++ linux-2.6/include/asm-powerpc/oprofile_impl.h 2006-03-26 17:55:19.000000000 +1100
@@ -35,9 +35,6 @@ struct op_system_config {
#endif
unsigned long enable_kernel;
unsigned long enable_user;
-#ifdef CONFIG_PPC64
- unsigned long backtrace_spinlocks;
-#endif
};
/* Per-arch configuration */
^ permalink raw reply
* [PATCH] powerpc: Add oprofile calltrace support
From: Anton Blanchard @ 2006-03-27 0:57 UTC (permalink / raw)
To: linuxppc-dev; +Cc: bcr6, paulus
In-Reply-To: <20060327004618.GB4962@krispykreme>
From: Brian Rogan <bcr6@cornell.edu>
Add oprofile calltrace support to powerpc. Disable spinlock backtracing
now we can use calltrace info.
(Updated to work on both 32bit and 64bit by me).
Signed-off-by: Anton Blanchard <anton@samba.org>
---
This patch depends on a patch currently in -mm:
http://marc.theaimsgroup.com/?l=linux-kernel&m=114333745914386&w=2
Index: build/arch/powerpc/oprofile/backtrace.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ build/arch/powerpc/oprofile/backtrace.c 2006-03-26 15:13:57.000000000 +1000
@@ -0,0 +1,126 @@
+/**
+ * Copyright (C) 2005 Brian Rogan <bcr6@cornell.edu>, IBM
+ *
+ * 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/sched.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+
+#define STACK_SP(STACK) *(STACK)
+
+#define STACK_LR64(STACK) *((unsigned long *)(STACK) + 2)
+#define STACK_LR32(STACK) *((unsigned int *)(STACK) + 1)
+
+#ifdef CONFIG_PPC64
+#define STACK_LR(STACK) STACK_LR64(STACK)
+#else
+#define STACK_LR(STACK) STACK_LR32(STACK)
+#endif
+
+static unsigned int user_getsp32(unsigned int sp, int is_first)
+{
+ unsigned int stack_frame[2];
+
+ if (!access_ok(VERIFY_READ, sp, sizeof(stack_frame)))
+ return 0;
+
+ /*
+ * The most likely reason for this is that we returned -EFAULT,
+ * which means that we've done all that we can do from
+ * interrupt context.
+ */
+ if (__copy_from_user_inatomic(stack_frame, (void *)(long)sp,
+ sizeof(stack_frame)))
+ return 0;
+
+ if (!is_first)
+ oprofile_add_trace(STACK_LR32(stack_frame));
+
+ /*
+ * We do not enforce increasing stack addresses here because
+ * we may transition to a different stack, eg a signal handler.
+ */
+ return STACK_SP(stack_frame);
+}
+
+#ifdef CONFIG_PPC64
+static unsigned long user_getsp64(unsigned long sp, int is_first)
+{
+ unsigned long stack_frame[3];
+
+ if (!access_ok(VERIFY_READ, sp, sizeof(stack_frame)))
+ return 0;
+
+ if (__copy_from_user_inatomic(stack_frame, (void *)sp,
+ sizeof(stack_frame)))
+ return 0;
+
+ if (!is_first)
+ oprofile_add_trace(STACK_LR64(stack_frame));
+
+ return STACK_SP(stack_frame);
+}
+#endif
+
+static unsigned long kernel_getsp(unsigned long sp, int is_first)
+{
+ unsigned long *stack_frame = (unsigned long *)sp;
+
+ if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD))
+ return 0;
+
+ if (!is_first)
+ oprofile_add_trace(STACK_LR(stack_frame));
+
+ /*
+ * We do not enforce increasing stack addresses here because
+ * we might be transitioning from an interrupt stack to a kernel
+ * stack. validate_sp() is designed to understand this, so just
+ * use it.
+ */
+ return STACK_SP(stack_frame);
+}
+
+void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth)
+{
+ unsigned long sp = regs->gpr[1];
+ int first_frame = 1;
+
+ /* We ditch the top stackframe so need to loop through an extra time */
+ depth += 1;
+
+ if (!user_mode(regs)) {
+ while (depth--) {
+ sp = kernel_getsp(sp, first_frame);
+ if (!sp)
+ break;
+ first_frame = 0;
+ }
+ } else {
+#ifdef CONFIG_PPC64
+ if (!test_thread_flag(TIF_32BIT)) {
+ while (depth--) {
+ sp = user_getsp64(sp, first_frame);
+ if (!sp)
+ break;
+ first_frame = 0;
+ }
+
+ return;
+ }
+#endif
+
+ while (depth--) {
+ sp = user_getsp32(sp, first_frame);
+ if (!sp)
+ break;
+ first_frame = 0;
+ }
+ }
+}
Index: build/arch/powerpc/oprofile/common.c
===================================================================
--- build.orig/arch/powerpc/oprofile/common.c 2006-01-16 00:05:48.000000000 +1100
+++ build/arch/powerpc/oprofile/common.c 2006-03-26 13:09:34.000000000 +1000
@@ -126,8 +126,7 @@ static int op_powerpc_create_files(struc
sys.enable_kernel = 1;
sys.enable_user = 1;
#ifdef CONFIG_PPC64
- /* Turn on backtracing through spinlocks by default */
- sys.backtrace_spinlocks = 1;
+ sys.backtrace_spinlocks = 0;
#endif
return 0;
@@ -168,6 +167,7 @@ int __init oprofile_arch_init(struct opr
ops->shutdown = op_powerpc_shutdown;
ops->start = op_powerpc_start;
ops->stop = op_powerpc_stop;
+ ops->backtrace = op_powerpc_backtrace;
printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
ops->cpu_type);
Index: build/arch/powerpc/oprofile/Makefile
===================================================================
--- build.orig/arch/powerpc/oprofile/Makefile 2006-03-26 10:40:14.000000000 +1000
+++ build/arch/powerpc/oprofile/Makefile 2006-03-26 13:09:34.000000000 +1000
@@ -10,7 +10,7 @@ DRIVER_OBJS := $(addprefix ../../../driv
oprofilefs.o oprofile_stats.o \
timer_int.o )
-oprofile-y := $(DRIVER_OBJS) common.o
+oprofile-y := $(DRIVER_OBJS) common.o backtrace.o
oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o
oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o
oprofile-$(CONFIG_PPC32) += op_model_7450.o
Index: build/arch/powerpc/oprofile/op_model_power4.c
===================================================================
--- build.orig/arch/powerpc/oprofile/op_model_power4.c 2006-03-24 15:51:18.000000000 +1100
+++ build/arch/powerpc/oprofile/op_model_power4.c 2006-03-26 13:09:34.000000000 +1000
@@ -293,7 +293,7 @@ static void power4_handle_interrupt(stru
val = ctr_read(i);
if (val < 0) {
if (oprofile_running && ctr[i].enabled) {
- oprofile_add_pc(pc, is_kernel, i);
+ oprofile_add_ext_sample(pc, regs, i, is_kernel);
ctr_write(i, reset_value[i]);
} else {
ctr_write(i, 0);
Index: build/include/asm-powerpc/oprofile_impl.h
===================================================================
--- build.orig/include/asm-powerpc/oprofile_impl.h 2006-03-26 12:48:01.000000000 +1000
+++ build/include/asm-powerpc/oprofile_impl.h 2006-03-26 13:09:34.000000000 +1000
@@ -126,5 +126,7 @@ static inline void ctr_write(unsigned in
}
#endif /* !CONFIG_FSL_BOOKE */
+extern void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth);
+
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_OPROFILE_IMPL_H */
^ permalink raw reply
* [PATCH] powerpc: export validate_sp for oprofile calltrace
From: Anton Blanchard @ 2006-03-27 0:46 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
In-Reply-To: <20060327002329.GA4962@krispykreme>
Export validate_sp so we can use it in the oprofile calltrace code.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: build/arch/powerpc/kernel/process.c
===================================================================
--- build.orig/arch/powerpc/kernel/process.c 2006-03-26 10:39:29.000000000 +1000
+++ build/arch/powerpc/kernel/process.c 2006-03-26 12:48:03.000000000 +1000
@@ -767,7 +767,7 @@ out:
return error;
}
-static int validate_sp(unsigned long sp, struct task_struct *p,
+int validate_sp(unsigned long sp, struct task_struct *p,
unsigned long nbytes)
{
unsigned long stack_page = (unsigned long)task_stack_page(p);
@@ -805,6 +805,8 @@ static int validate_sp(unsigned long sp,
#define FRAME_MARKER 2
#endif
+EXPORT_SYMBOL(validate_sp);
+
unsigned long get_wchan(struct task_struct *p)
{
unsigned long ip, sp;
Index: build/include/asm-powerpc/processor.h
===================================================================
--- build.orig/include/asm-powerpc/processor.h 2006-03-24 15:51:22.000000000 +1100
+++ build/include/asm-powerpc/processor.h 2006-03-26 12:48:03.000000000 +1000
@@ -251,6 +251,10 @@ static inline unsigned long __pack_fe01(
#define cpu_relax() barrier()
#endif
+/* Check that a certain kernel stack pointer is valid in task_struct p */
+int validate_sp(unsigned long sp, struct task_struct *p,
+ unsigned long nbytes);
+
/*
* Prefetch macros.
*/
^ permalink raw reply
* [PATCH] powerpc: Remove some ifdefs in oprofile_impl.h
From: Anton Blanchard @ 2006-03-27 0:23 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
- No one uses op_counter_config.valid, so remove it
- No need to ifdef around function protypes.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: linux-2.6/include/asm-powerpc/oprofile_impl.h
===================================================================
--- linux-2.6.orig/include/asm-powerpc/oprofile_impl.h 2006-03-26 12:17:23.000000000 +1100
+++ linux-2.6/include/asm-powerpc/oprofile_impl.h 2006-03-26 12:21:13.000000000 +1100
@@ -17,9 +17,6 @@
/* Per-counter configuration as set via oprofilefs. */
struct op_counter_config {
-#ifdef __powerpc64__
- unsigned long valid;
-#endif
unsigned long enabled;
unsigned long event;
unsigned long count;
@@ -56,17 +53,12 @@ struct op_powerpc_model {
int num_counters;
};
-#ifdef CONFIG_FSL_BOOKE
extern struct op_powerpc_model op_model_fsl_booke;
-#else /* Otherwise, it's classic */
-
-#ifdef CONFIG_PPC64
extern struct op_powerpc_model op_model_rs64;
extern struct op_powerpc_model op_model_power4;
-
-#else /* Otherwise, CONFIG_PPC32 */
extern struct op_powerpc_model op_model_7450;
-#endif
+
+#ifndef CONFIG_FSL_BOOKE
/* All the classic PPC parts use these */
static inline unsigned int ctr_read(unsigned int i)
^ permalink raw reply
* Re: [PATCH 0/4] MPC52xx updates : lite5200b + ide support
From: Paul Mackerras @ 2006-03-26 22:20 UTC (permalink / raw)
To: Sylvain Munaut; +Cc: Linux PPC embedded
In-Reply-To: <0.20060326_133535_93e6_tnt@patchsend.246tNt.com>
Sylvain Munaut writes:
> This set of updates mainly adds support for the new lite5200B
> devboard from Freescale and support for IDE.
>
> Theses have been posted on the ppc-embedded mailing list some
> time ago, they've been tested and reported working by a few people,
> so Paul it'd be nice to get those merged upstream. If you were
> not the one to cc about this, let me know, I'll forward those
> to Andrew.
I'll handle patches 1-3, but you will need to send the IDE patch to
the IDE maintainer, Bartlomiej Zolnierkiewicz
<B.Zolnierkiewicz@elka.pw.edu.pl>.
Paul.
^ permalink raw reply
* Re: make install on ppc
From: Hans Fugal @ 2006-03-26 21:44 UTC (permalink / raw)
To: Hollis Blanchard; +Cc: linuxppc-dev list
In-Reply-To: <ce3dc94b4e52e43d812f3783b6fc8b42@penguinppc.org>
Hollis Blanchard wrote:
> On Mar 21, 2006, at 8:08 AM, Hans Fugal wrote:
>
>> Is there something that stops us from having a make install target for
>> ppc?
>
> Why do you want it, and what would it do? Clearly not many people have
> needed it so far...
I bet a lot of people have typed it, wished it was there, then worked
around it. That's what I've been doing for a year now.
It doesn't do much - basically it has the proper dependencies and runs
installkernel with the appropriate arguments (as indicated by `make help`).
Thanks
^ permalink raw reply
* Re: make install on ppc
From: Arnd Bergmann @ 2006-03-26 20:43 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Hans Fugal
In-Reply-To: <ce3dc94b4e52e43d812f3783b6fc8b42@penguinppc.org>
Am Sunday 26 March 2006 21:26 schrieb Hollis Blanchard:
> On Mar 21, 2006, at 8:08 AM, Hans Fugal wrote:
> > Is there something that stops us from having a make install target for
> > ppc?
>
> Why do you want it, and what would it do? Clearly not many people have
> needed it so far...
I've missed it a few times, typing 'make install' by habit, but thought
it was a bug in my own setup, so I didn't bother looking what was
missing.
Arnd <><
^ permalink raw reply
* Re: make install on ppc
From: Hollis Blanchard @ 2006-03-26 19:26 UTC (permalink / raw)
To: Hans Fugal; +Cc: linuxppc-dev list
In-Reply-To: <442008EE.6040808@fugal.net>
On Mar 21, 2006, at 8:08 AM, Hans Fugal wrote:
> Is there something that stops us from having a make install target for
> ppc?
Why do you want it, and what would it do? Clearly not many people have
needed it so far...
-Hollis
^ permalink raw reply
* [PATCH 4/4] ppc32/ide: Add support for MPC52xx on-chip ATA controller
From: Sylvain Munaut @ 2006-03-26 11:38 UTC (permalink / raw)
To: Linux PPC embedded; +Cc: Paul Mackerras
In-Reply-To: <0.20060326_133535_93e6_tnt@patchsend.246tNt.com>
ppc32/ide: Add support for MPC52xx on-chip ATA controller
This patch adds initial support for Freescale MPC52xx on-chip ATA
controller. It's currently PIO-mode only and all the erratas are
not handled since some of them requires hw tricks ...
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
commit f3180ffadd5dddcfa9d11da4f7637e3e907e6aaa
tree d9bf294057a0dcdda25ba6c6ea3fcc9748d87e93
parent 67015426ff51ba857b7678a993f4ffd6def1941e
author Sylvain Munaut <tnt@246tNt.com> 1139147442 +0100
committer Sylvain Munaut <tnt@246tNt.com> 1143312600 +0100
drivers/ide/Kconfig | 4
drivers/ide/Makefile | 1
drivers/ide/ppc/mpc52xx_ide.c | 420 +++++++++++++++++++++++++++++++++++++
drivers/ide/ppc/mpc52xx_ide.h | 129 +++++++++++
drivers/ide/ppc/mpc52xx_ide_iops.c | 151 +++++++++++++
include/linux/ide.h | 2
6 files changed, 706 insertions(+), 1 deletion(-)
---
f3180ffadd5dddcfa9d11da4f7637e3e907e6aaa
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index d633081..3a10fec 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -962,6 +962,10 @@ config IDE_EXT_DIRECT
endchoice
+config BLK_DEV_MPC52xx_IDE
+ tristate "MPC52xx Builtin IDE support"
+ depends on PPC_MPC52xx && IDE=y
+
# no isa -> no vlb
config IDE_CHIPSETS
bool "Other IDE chipset support"
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index 569fae7..fcca1f3 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -34,6 +34,7 @@ ide-core-$(CONFIG_BLK_DEV_MAC_IDE) += le
ide-core-$(CONFIG_BLK_DEV_Q40IDE) += legacy/q40ide.o
# built-in only drivers from ppc/
+ide-core-$(CONFIG_BLK_DEV_MPC52xx_IDE) += ppc/mpc52xx_ide.o ppc/mpc52xx_ide_iops.o
ide-core-$(CONFIG_BLK_DEV_MPC8xx_IDE) += ppc/mpc8xx.o
ide-core-$(CONFIG_BLK_DEV_IDE_PMAC) += ppc/pmac.o
diff --git a/drivers/ide/ppc/mpc52xx_ide.c b/drivers/ide/ppc/mpc52xx_ide.c
new file mode 100644
index 0000000..5970f7b
--- /dev/null
+++ b/drivers/ide/ppc/mpc52xx_ide.c
@@ -0,0 +1,420 @@
+/*
+ * drivers/ide/ppc/mpc52xx_ide.h
+ *
+ * Driver for the Freescale MPC52xx on-chip IDE interface
+ *
+ *
+ * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Mipsys - Benjamin Herrenschmidt
+ *
+ * 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.
+ */
+
+#undef REALLY_SLOW_IO /* most systems can safely undef this */
+
+#include <linux/config.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+#include <asm/ppcboot.h>
+
+#include "mpc52xx_ide.h"
+
+
+
+/* Private structures used by the driver */
+struct mpc52xx_ata_timings {
+ u32 pio1;
+ u32 pio2;
+ u32 mdma1;
+ u32 mdma2;
+ u32 udma1;
+ u32 udma2;
+ u32 udma3;
+ u32 udma4;
+ u32 udma5;
+ int using_udma;
+};
+
+struct mpc52xx_ide_priv {
+ unsigned int ipb_period; /* in ps */
+ struct mpc52xx_ata __iomem *ata_regs;
+ struct mpc52xx_ata_timings timings[2];
+};
+
+/* ATAPI-4 PIO specs (arranged for the 5200, cfr User Manual) */
+/* numbers in ns, extrapolation done by code */
+static int ataspec_t0[5] = {600, 383, 240, 180, 120};
+static int ataspec_t1[5] = { 70, 50, 30, 30, 25};
+static int ataspec_t2_8[5] = {290, 290, 290, 80, 70};
+static int ataspec_t2_16[5] = {165, 125, 100, 80, 70};
+static int ataspec_t2i[5] = { 0, 0, 0, 70, 25};
+static int ataspec_t4[5] = { 30, 20, 15, 10, 10};
+static int ataspec_ta[5] = { 35, 35, 35, 35, 35};
+
+/* Helpers to compute timing parameters */
+#define CALC_CLK_VALUE_UP(c,v) (((v) + c - 1) / c)
+
+
+/* ======================================================================== */
+/* IDE Driver & Aux functions */
+/* ======================================================================== */
+
+static void
+mpc52xx_ide_apply_timing(
+ struct mpc52xx_ata __iomem *regs, struct mpc52xx_ata_timings *timing)
+{
+ out_be32(®s->pio1, timing->pio1);
+ out_be32(®s->pio2, timing->pio2);
+ out_be32(®s->mdma1, timing->mdma1);
+ out_be32(®s->mdma2, timing->mdma2);
+ out_be32(®s->udma1, timing->udma1);
+ out_be32(®s->udma2, timing->udma2);
+ out_be32(®s->udma3, timing->udma3);
+ out_be32(®s->udma4, timing->udma4);
+ out_be32(®s->udma5, timing->udma5);
+}
+
+static void
+mpc52xx_ide_compute_pio_timing(
+ struct mpc52xx_ata_timings *timing, unsigned int ipb_period, u8 pio)
+{
+ u32 t0, t2_8, t2_16, t2i, t4, t1, ta;
+
+ /* We add 1 as a 'margin' */
+ t0 = 1 + CALC_CLK_VALUE_UP(ipb_period, 1000*ataspec_t0[pio]);
+ t2_8 = 1 + CALC_CLK_VALUE_UP(ipb_period, 1000*ataspec_t2_8[pio]);
+ t2_16 = 1 + CALC_CLK_VALUE_UP(ipb_period, 1000*ataspec_t2_16[pio]);
+ t2i = 1 + CALC_CLK_VALUE_UP(ipb_period, 1000*ataspec_t2i[pio]);
+ t4 = 1 + CALC_CLK_VALUE_UP(ipb_period, 1000*ataspec_t4[pio]);
+ t1 = 1 + CALC_CLK_VALUE_UP(ipb_period, 1000*ataspec_t1[pio]);
+ ta = 1 + CALC_CLK_VALUE_UP(ipb_period, 1000*ataspec_ta[pio]);
+
+ timing->pio1 = (t0 << 24) | (t2_8 << 16) | (t2_16 << 8) | (t2i);
+ timing->pio2 = (t4 << 24) | (t1 << 16) | (ta << 8);
+}
+
+
+static void
+mpc52xx_ide_tuneproc(ide_drive_t *drive, u8 pio)
+{
+ struct mpc52xx_ide_priv *priv = drive->hwif->hwif_data;
+ struct mpc52xx_ata __iomem *regs = priv->ata_regs;
+ int w = drive->select.b.unit & 0x01;
+
+ pio = ide_get_best_pio_mode(drive, pio, 5, NULL);
+
+ printk("%s: Setting PIO %d timings\n", drive->name, pio);
+
+ mpc52xx_ide_compute_pio_timing(&priv->timings[w], priv->ipb_period, pio);
+
+ if (drive->select.all == HWIF(drive)->INB(IDE_SELECT_REG))
+ mpc52xx_ide_apply_timing(regs, &priv->timings[w]);
+
+ /* Should we do it here or only in speedproc ? */
+ ide_config_drive_speed(drive, pio + XFER_PIO_0);
+}
+
+static int
+mpc52xx_ide_speedproc(ide_drive_t *drive, u8 speed)
+{
+ /* Configure PIO Mode */
+ if (speed >= XFER_PIO_0 && speed <= XFER_PIO_4) {
+ mpc52xx_ide_tuneproc(drive, speed - XFER_PIO_0);
+ return 0;
+ }
+
+ /* DMA settings currently unsupported */
+ printk(KERN_ERR
+ "mpc52xx-ide: speedproc called with unsupported mode %d\n",
+ speed);
+
+ return 1;
+}
+
+static void
+mpc52xx_ide_selectproc(ide_drive_t *drive)
+{
+ /* Change the PIO timings to the ones of the
+ currently selected drive */
+ struct mpc52xx_ide_priv *priv = drive->hwif->hwif_data;
+ struct mpc52xx_ata __iomem *regs = priv->ata_regs;
+
+ mpc52xx_ide_apply_timing(regs,
+ &priv->timings[drive->select.b.unit & 0x01]);
+}
+
+
+static int
+mpc52xx_ide_setup(
+ struct mpc52xx_ata __iomem *regs, struct mpc52xx_ide_priv *priv)
+{
+ /* Vars */
+ extern bd_t __res;
+ bd_t *bd = (bd_t *)&__res;
+ int tslot;
+
+ /* All sample code do this */
+ out_be32(®s->share_cnt, 0);
+
+ /* Configure & Reset host */
+ out_be32(®s->config,
+ MPC52xx_ATA_HOSTCONF_IE |
+ MPC52xx_ATA_HOSTCONF_IORDY |
+ MPC52xx_ATA_HOSTCONF_SMR |
+ MPC52xx_ATA_HOSTCONF_FR);
+ udelay(10);
+ out_be32(®s->config,
+ MPC52xx_ATA_HOSTCONF_IE |
+ MPC52xx_ATA_HOSTCONF_IORDY);
+
+ /* Get IPB bus period */
+ priv->ipb_period = 1000000000 / (bd->bi_ipbfreq/1000);
+
+ /* Try to set the time slot to around 1us = 1000000 ps */
+ tslot = CALC_CLK_VALUE_UP(priv->ipb_period, 1000000);
+ out_be32(®s->share_cnt, tslot << 16);
+
+ /* Init imings to PIO0 (safest) */
+ memset(priv->timings, 0x00, 2*sizeof(struct mpc52xx_ata_timings));
+
+ mpc52xx_ide_compute_pio_timing(&priv->timings[0], priv->ipb_period, 0);
+ mpc52xx_ide_compute_pio_timing(&priv->timings[1], priv->ipb_period, 0);
+
+ mpc52xx_ide_apply_timing(regs, &priv->timings[0]);
+
+ return 0;
+}
+
+static void
+mpc52xx_ide_setup_hwif_ports(hw_regs_t *hw, struct mpc52xx_ata __iomem *regs)
+{
+ /* It's MMIO and we handle all the io ops ourself, */
+ /* so theses address are really virtual addresses */
+ hw->io_ports[IDE_DATA_OFFSET] = (unsigned long) ®s->tf_data;
+ hw->io_ports[IDE_ERROR_OFFSET] = (unsigned long) ®s->tf_features;
+ hw->io_ports[IDE_NSECTOR_OFFSET] = (unsigned long) ®s->tf_sec_count;
+ hw->io_ports[IDE_SECTOR_OFFSET] = (unsigned long) ®s->tf_sec_num;
+ hw->io_ports[IDE_LCYL_OFFSET] = (unsigned long) ®s->tf_cyl_low;
+ hw->io_ports[IDE_HCYL_OFFSET] = (unsigned long) ®s->tf_cyl_high;
+ hw->io_ports[IDE_SELECT_OFFSET] = (unsigned long) ®s->tf_dev_head;
+ hw->io_ports[IDE_STATUS_OFFSET] = (unsigned long) ®s->tf_command;
+ hw->io_ports[IDE_CONTROL_OFFSET] = (unsigned long) ®s->tf_control;
+}
+
+
+/* ======================================================================== */
+/* Platform Driver */
+/* ======================================================================== */
+
+static int __devinit
+mpc52xx_ide_probe(struct platform_device *dev)
+{
+ /* Vars */
+ ide_hwif_t *hwif;
+ struct mpc52xx_ide_priv *priv;
+ struct mpc52xx_gpio __iomem *gpio_regs = NULL;
+ struct mpc52xx_ata __iomem *ata_regs = NULL;
+ int ata_irq;
+ struct resource *res_mem;
+ u32 reg;
+ int i, rv;
+
+ /* Get an empty slot */
+ for (i=0; i<MAX_HWIFS && ide_hwifs[i].io_ports[IDE_DATA_OFFSET]; i++);
+ if (i >= MAX_HWIFS) {
+ printk(KERN_ERR "mpc52xx-ide: No free hwif slot !\n");
+ return -ENOMEM;
+ }
+
+ hwif = &ide_hwifs[i];
+
+ /* Check port muxing for compatibility */
+ gpio_regs = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE);
+ if (!gpio_regs) {
+ printk(KERN_ERR
+ "mpc52xx-ide: Unable to ioremap MPC52xx_GPIO zone\n");
+ return -ENOMEM;
+ }
+
+ reg = in_be32(&gpio_regs->port_config);
+ iounmap(gpio_regs);
+
+ if (!(reg & 0x03000000ul)) {
+ printk(KERN_ERR
+ "mpc52xx-ide: Invalid port config, no ATA CS !\n");
+ return -ENODEV;
+ }
+
+ /* Get the resources of this device */
+ ata_irq = platform_get_irq(dev, 0);
+ res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
+
+ if (ata_irq<0 || res_mem==NULL) {
+ printk(KERN_ERR "mpc52xx-ide: Invalid resource set !\n");
+ return -EINVAL;
+ }
+
+ if (!request_mem_region(res_mem->start, sizeof(struct mpc52xx_ata),
+ "mpc52xx-ide")) {
+ printk(KERN_ERR "mpc52xx-ide: Memory zone unavailable !\n");
+ return -EBUSY;
+ }
+
+ ata_regs = ioremap(res_mem->start, sizeof(struct mpc52xx_ata));
+ if (!ata_regs) {
+ printk(KERN_ERR
+ "mpc52xx-ide: Unable to ioremap ATA registers\n");
+ rv = -ENOMEM;
+ goto error;
+ }
+
+ /* Setup private structure */
+ priv = kmalloc(sizeof(struct mpc52xx_ide_priv), GFP_ATOMIC);
+ if (!priv) {
+ printk(KERN_ERR
+ "mpc52xx-ide: Can't allocate private structure !\n");
+ rv = -ENOMEM;
+ goto error;
+ }
+
+ priv->ata_regs = ata_regs;
+
+ /* Setup the ATA controller */
+ rv = mpc52xx_ide_setup(ata_regs, priv);
+ if (rv) {
+ printk(KERN_ERR "mpc52xx-ide: Controller setup failed !\n");
+ goto error;
+ }
+
+ /* Setup the hwif structure */
+ hwif->irq = ata_irq;
+ hwif->mmio = 2;
+ mpc52xx_ide_setup_hwif_iops(hwif);
+ mpc52xx_ide_setup_hwif_ports(&hwif->hw, ata_regs);
+ memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
+
+ hwif->atapi_dma = 0;
+ hwif->ultra_mask = 0x00;
+ hwif->mwdma_mask = 0x00;
+ hwif->swdma_mask = 0x00;
+ hwif->chipset = ide_mpc52xx;
+ hwif->tuneproc = mpc52xx_ide_tuneproc;
+ hwif->speedproc = mpc52xx_ide_speedproc;
+ hwif->selectproc = mpc52xx_ide_selectproc;
+ hwif->noprobe = 0;
+ hwif->hold = 1;
+ hwif->autodma = 0;
+ hwif->udma_four = 0;
+ hwif->no_lba48 = 1; /* FIXME ? Did some one test that ? */
+ hwif->no_lba48_dma = 1;
+
+ hwif->drives[0].unmask = 1;
+ hwif->drives[0].autotune = 0; /* default */
+ hwif->drives[0].autodma = hwif->autodma;
+ hwif->drives[0].no_io_32bit = 1; /* Anyone tried ? */
+
+ hwif->drives[1].unmask = 1;
+ hwif->drives[1].autotune = 0; /* default */
+ hwif->drives[1].autodma = hwif->autodma;
+ hwif->drives[1].no_io_32bit = 1; /* Anyone tried ? */
+
+ hwif->hwif_data = priv;
+ platform_set_drvdata(dev, hwif);
+
+ /* Lauch probe */
+ probe_hwif_init(hwif);
+
+ /* We're good ! */
+ printk(KERN_INFO
+ "mpc52xx-ide: Setup successful for %s (mem=%08lx-%08lx irq=%d)\n",
+ hwif->name, res_mem->start, res_mem->end, ata_irq);
+
+ return 0;
+
+
+ /* Error path */
+error:
+ if (ata_regs)
+ iounmap(ata_regs);
+
+ release_mem_region(res_mem->start, sizeof(struct mpc52xx_ata));
+
+ return rv;
+}
+
+static int
+mpc52xx_ide_remove(struct platform_device *dev)
+{
+ ide_hwif_t *hwif = platform_get_drvdata(dev);
+ struct mpc52xx_ide_priv *priv = hwif->hwif_data;
+ struct resource *res_mem;
+
+ ide_unregister(hwif - ide_hwifs);
+
+ iounmap(priv->ata_regs);
+
+ res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ release_mem_region(res_mem->start, sizeof(struct mpc52xx_ata));
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int
+mpc52xx_ide_suspend(struct platform_device *dev, pm_message_t state)
+{
+ return 0; /* FIXME : What to do here ? */
+}
+
+static int
+mpc52xx_ide_resume(struct platform_device *dev)
+{
+ return 0; /* FIXME : What to do here ? */
+}
+#endif
+
+static struct platform_driver mpc52xx_ide_platform_driver = {
+ .probe = mpc52xx_ide_probe,
+ .remove = mpc52xx_ide_remove,
+#ifdef CONFIG_PM
+ .suspend = mpc52xx_ide_suspend,
+ .resume = mpc52xx_ide_resume,
+#endif
+ .driver = {
+ .name = "mpc52xx-ata",
+ },
+};
+
+
+/* ======================================================================== */
+/* Module */
+/* ======================================================================== */
+
+static int __init
+mpc52xx_ide_init(void)
+{
+ printk(KERN_INFO "ide: MPC52xx IDE/ATA driver\n");
+ return platform_driver_register(&mpc52xx_ide_platform_driver);
+}
+
+static void __exit
+mpc52xx_ide_exit(void)
+{
+ platform_driver_unregister(&mpc52xx_ide_platform_driver);
+}
+
+
+module_init(mpc52xx_ide_init);
+module_exit(mpc52xx_ide_exit);
+
+MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
+MODULE_DESCRIPTION("Freescale MPC52xx IDE/ATA driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/ide/ppc/mpc52xx_ide.h b/drivers/ide/ppc/mpc52xx_ide.h
new file mode 100644
index 0000000..e2490a8
--- /dev/null
+++ b/drivers/ide/ppc/mpc52xx_ide.h
@@ -0,0 +1,129 @@
+/*
+ * drivers/ide/ppc/mpc52xx_ide.h
+ *
+ * Definitions for the Freescale MPC52xx on-chip IDE interface
+ *
+ *
+ * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Mipsys - Benjamin Herrenschmidt
+ *
+ * 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 __MPC52xx_IDE_H__
+#define __MPC52xx_IDE_H__
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <asm/types.h>
+#include <asm/io.h>
+
+
+
+/* Bit definitions inside the registers */
+
+#define MPC52xx_ATA_HOSTCONF_SMR 0x80000000UL /* State machine reset */
+#define MPC52xx_ATA_HOSTCONF_FR 0x40000000UL /* FIFO Reset */
+#define MPC52xx_ATA_HOSTCONF_IE 0x02000000UL /* Enable interrupt in PIO */
+#define MPC52xx_ATA_HOSTCONF_IORDY 0x01000000UL /* Drive supports IORDY protocol */
+
+#define MPC52xx_ATA_HOSTSTAT_TIP 0x80000000UL /* Transaction in progress */
+#define MPC52xx_ATA_HOSTSTAT_UREP 0x40000000UL /* UDMA Read Extended Pause */
+#define MPC52xx_ATA_HOSTSTAT_RERR 0x02000000UL /* Read Error */
+#define MPC52xx_ATA_HOSTSTAT_WERR 0x01000000UL /* Write Error */
+
+#define MPC52xx_ATA_FIFOSTAT_EMPTY 0x01 /* FIFO Empty */
+
+#define MPC52xx_ATA_DMAMODE_WRITE 0x01 /* Write DMA */
+#define MPC52xx_ATA_DMAMODE_READ 0x02 /* Read DMA */
+#define MPC52xx_ATA_DMAMODE_UDMA 0x04 /* UDMA enabled */
+#define MPC52xx_ATA_DMAMODE_IE 0x08 /* Enable drive interrupt to CPU in DMA mode */
+#define MPC52xx_ATA_DMAMODE_FE 0x10 /* FIFO Flush enable in Rx mode */
+#define MPC52xx_ATA_DMAMODE_FR 0x20 /* FIFO Reset */
+#define MPC52xx_ATA_DMAMODE_HUT 0x40 /* Host UDMA burst terminate */
+
+
+/* Structure of the hardware registers */
+struct mpc52xx_ata {
+
+ /* Host interface registers */
+ u32 config; /* ATA + 0x00 Host configuration */
+ u32 host_status; /* ATA + 0x04 Host controller status */
+ u32 pio1; /* ATA + 0x08 PIO Timing 1 */
+ u32 pio2; /* ATA + 0x0c PIO Timing 2 */
+ u32 mdma1; /* ATA + 0x10 MDMA Timing 1 */
+ u32 mdma2; /* ATA + 0x14 MDMA Timing 2 */
+ u32 udma1; /* ATA + 0x18 UDMA Timing 1 */
+ u32 udma2; /* ATA + 0x1c UDMA Timing 2 */
+ u32 udma3; /* ATA + 0x20 UDMA Timing 3 */
+ u32 udma4; /* ATA + 0x24 UDMA Timing 4 */
+ u32 udma5; /* ATA + 0x28 UDMA Timing 5 */
+ u32 share_cnt; /* ATA + 0x2c ATA share counter */
+ u32 reserved0[3];
+
+ /* FIFO registers */
+ u32 fifo_data; /* ATA + 0x3c */
+ u8 fifo_status_frame; /* ATA + 0x40 */
+ u8 fifo_status; /* ATA + 0x41 */
+ u16 reserved7[1];
+ u8 fifo_control; /* ATA + 0x44 */
+ u8 reserved8[5];
+ u16 fifo_alarm; /* ATA + 0x4a */
+ u16 reserved9;
+ u16 fifo_rdp; /* ATA + 0x4e */
+ u16 reserved10;
+ u16 fifo_wrp; /* ATA + 0x52 */
+ u16 reserved11;
+ u16 fifo_lfrdp; /* ATA + 0x56 */
+ u16 reserved12;
+ u16 fifo_lfwrp; /* ATA + 0x5a */
+
+ /* Drive TaskFile registers */
+ u8 tf_control; /* ATA + 0x5c TASKFILE Control/Alt Status */
+ u8 reserved13[3];
+ u16 tf_data; /* ATA + 0x60 TASKFILE Data */
+ u16 reserved14;
+ u8 tf_features; /* ATA + 0x64 TASKFILE Features/Error */
+ u8 reserved15[3];
+ u8 tf_sec_count; /* ATA + 0x68 TASKFILE Sector Count */
+ u8 reserved16[3];
+ u8 tf_sec_num; /* ATA + 0x6c TASKFILE Sector Number */
+ u8 reserved17[3];
+ u8 tf_cyl_low; /* ATA + 0x70 TASKFILE Cylinder Low */
+ u8 reserved18[3];
+ u8 tf_cyl_high; /* ATA + 0x74 TASKFILE Cylinder High */
+ u8 reserved19[3];
+ u8 tf_dev_head; /* ATA + 0x78 TASKFILE Device/Head */
+ u8 reserved20[3];
+ u8 tf_command; /* ATA + 0x7c TASKFILE Command/Status */
+ u8 dma_mode; /* ATA + 0x7d ATA Host DMA Mode configuration */
+ u8 reserved21[2];
+};
+
+
+/* Function definition */
+
+static inline void
+mpc52xx_ide_wait_tip_bit_clear(struct mpc52xx_ata __iomem *regs)
+{
+ int timeout = 1000;
+
+ while (in_be32(®s->host_status) & MPC52xx_ATA_HOSTSTAT_TIP)
+ if (timeout-- == 0) {
+ printk(KERN_ERR
+ "mpc52xx-ide: Timeout waiting for TIP clear\n");
+ break;
+ }
+ udelay(10); /* FIXME: Necessary ??? */
+}
+
+extern void mpc52xx_ide_setup_hwif_iops(ide_hwif_t *hwif);
+
+
+#endif /* __MPC52xx_IDE_H__ */
+
diff --git a/drivers/ide/ppc/mpc52xx_ide_iops.c b/drivers/ide/ppc/mpc52xx_ide_iops.c
new file mode 100644
index 0000000..6ced54e
--- /dev/null
+++ b/drivers/ide/ppc/mpc52xx_ide_iops.c
@@ -0,0 +1,151 @@
+/*
+ * drivers/ide/ppc/mpc52xx_ide_iops.c
+ *
+ * Utility functions for MPC52xx on-chip IDE interface
+ *
+ *
+ * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Mipsys - Benjamin Herrenschmidt
+ *
+ * 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/config.h>
+#include <linux/kernel.h>
+#include <linux/ide.h>
+#include <asm/io.h>
+
+#include "mpc52xx_ide.h"
+
+
+
+static u8
+mpc52xx_ide_inb(unsigned long port)
+{
+ struct mpc52xx_ata __iomem *ata_regs =
+ (struct mpc52xx_ata __iomem *)(port & ~0xfful);
+
+ mpc52xx_ide_wait_tip_bit_clear(ata_regs);
+ return (u8) readb((void __iomem *) port);
+}
+
+static u16
+mpc52xx_ide_inw(unsigned long port)
+{
+ struct mpc52xx_ata __iomem *ata_regs =
+ (struct mpc52xx_ata __iomem *)(port & ~0xfful);
+
+ mpc52xx_ide_wait_tip_bit_clear(ata_regs);
+ return (u16) readw((void __iomem *) port);
+}
+
+static void
+mpc52xx_ide_insw(unsigned long port, void *addr, u32 count)
+{
+ struct mpc52xx_ata __iomem *ata_regs =
+ (struct mpc52xx_ata __iomem *)(port & ~0xfful);
+
+ mpc52xx_ide_wait_tip_bit_clear(ata_regs);
+ __ide_mm_insw((void __iomem *) port, addr, count);
+}
+
+static u32
+mpc52xx_ide_inl(unsigned long port)
+{
+ struct mpc52xx_ata __iomem *ata_regs =
+ (struct mpc52xx_ata __iomem *)(port & ~0xfful);
+
+ mpc52xx_ide_wait_tip_bit_clear(ata_regs);
+ return (u32) readl((void __iomem *) port);
+}
+
+static void
+mpc52xx_ide_insl(unsigned long port, void *addr, u32 count)
+{
+ struct mpc52xx_ata __iomem *ata_regs =
+ (struct mpc52xx_ata __iomem *)(port & ~0xfful);
+
+ mpc52xx_ide_wait_tip_bit_clear(ata_regs);
+ __ide_mm_insl((void __iomem *) port, addr, count);
+}
+
+static void
+mpc52xx_ide_outb(u8 value, unsigned long port)
+{
+ struct mpc52xx_ata __iomem *ata_regs =
+ (struct mpc52xx_ata __iomem *)(port & ~0xfful);
+
+ mpc52xx_ide_wait_tip_bit_clear(ata_regs);
+ writeb(value, (void __iomem *) port);
+}
+
+static void
+mpc52xx_ide_outbsync(ide_drive_t *drive, u8 value, unsigned long port)
+{
+ struct mpc52xx_ata __iomem *ata_regs =
+ (struct mpc52xx_ata __iomem *)(port & ~0xfful);
+
+ mpc52xx_ide_wait_tip_bit_clear(ata_regs);
+ writeb(value, (void __iomem *) port);
+}
+
+
+static void
+mpc52xx_ide_outw(u16 value, unsigned long port)
+{
+ struct mpc52xx_ata __iomem *ata_regs =
+ (struct mpc52xx_ata __iomem *)(port & ~0xfful);
+
+ mpc52xx_ide_wait_tip_bit_clear(ata_regs);
+ writew(value, (void __iomem *) port);
+}
+
+static void
+mpc52xx_ide_outsw(unsigned long port, void *addr, u32 count)
+{
+ struct mpc52xx_ata __iomem *ata_regs =
+ (struct mpc52xx_ata __iomem *)(port & ~0xfful);
+
+ mpc52xx_ide_wait_tip_bit_clear(ata_regs);
+ __ide_mm_outsw((void __iomem *) port, addr, count);
+}
+
+static void
+mpc52xx_ide_outl(u32 value, unsigned long port)
+{
+ struct mpc52xx_ata __iomem *ata_regs =
+ (struct mpc52xx_ata __iomem *)(port & ~0xfful);
+
+ mpc52xx_ide_wait_tip_bit_clear(ata_regs);
+ writel(value, (void __iomem *) port);
+}
+
+static void
+mpc52xx_ide_outsl(unsigned long port, void *addr, u32 count)
+{
+ struct mpc52xx_ata __iomem *ata_regs =
+ (struct mpc52xx_ata __iomem *)(port & ~0xfful);
+
+ mpc52xx_ide_wait_tip_bit_clear(ata_regs);
+ __ide_mm_outsl((void __iomem *) port, addr, count);
+}
+
+
+void
+mpc52xx_ide_setup_hwif_iops(ide_hwif_t *hwif)
+{
+ hwif->OUTB = mpc52xx_ide_outb;
+ hwif->OUTBSYNC = mpc52xx_ide_outbsync;
+ hwif->OUTW = mpc52xx_ide_outw;
+ hwif->OUTL = mpc52xx_ide_outl;
+ hwif->OUTSW = mpc52xx_ide_outsw;
+ hwif->OUTSL = mpc52xx_ide_outsl;
+ hwif->INB = mpc52xx_ide_inb;
+ hwif->INW = mpc52xx_ide_inw;
+ hwif->INL = mpc52xx_ide_inl;
+ hwif->INSW = mpc52xx_ide_insw;
+ hwif->INSL = mpc52xx_ide_insl;
+}
+
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 8d2db41..793c70a 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -203,7 +203,7 @@ typedef enum { ide_unknown, ide_generic,
ide_rz1000, ide_trm290,
ide_cmd646, ide_cy82c693, ide_4drives,
ide_pmac, ide_etrax100, ide_acorn,
- ide_au1xxx, ide_forced
+ ide_au1xxx, ide_mpc52xx, ide_forced
} hwif_chipset_t;
/*
^ permalink raw reply related
* [PATCH 3/4] ppc32: Reorganize and complete MPC52xx initial cpu setup
From: Sylvain Munaut @ 2006-03-26 11:38 UTC (permalink / raw)
To: Linux PPC embedded; +Cc: Paul Mackerras
In-Reply-To: <0.20060326_133535_93e6_tnt@patchsend.246tNt.com>
ppc32: Reorganize and complete MPC52xx initial cpu setup
This patch splits up the CPU setup into a generic part and a
platform specific part. We also add a few missing init at the
same time.
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
commit 67015426ff51ba857b7678a993f4ffd6def1941e
tree cca92c1916ede8f67fe8d16987a54303c76f31f8
parent 37ffaaccad4fb48c8416e610aab4d3bed41dfc80
author Sylvain Munaut <tnt@246tNt.com> 1143311892 +0100
committer Sylvain Munaut <tnt@246tNt.com> 1143311892 +0100
arch/ppc/platforms/lite5200.c | 38 ++++++++-----------------------
arch/ppc/syslib/mpc52xx_setup.c | 48 ++++++++++++++++++++++++++++++++++++++++
include/asm-ppc/mpc52xx.h | 4 +++
3 files changed, 62 insertions(+), 28 deletions(-)
---
67015426ff51ba857b7678a993f4ffd6def1941e
diff --git a/arch/ppc/platforms/lite5200.c b/arch/ppc/platforms/lite5200.c
index d91efe1..fecbe9a 100644
--- a/arch/ppc/platforms/lite5200.c
+++ b/arch/ppc/platforms/lite5200.c
@@ -36,8 +36,6 @@
#include <asm/machdep.h>
#include <asm/pci-bridge.h>
-#include <syslib/mpc52xx_pci.h>
-
extern int powersave_nap;
@@ -99,34 +97,23 @@ lite5200_map_irq(struct pci_dev *dev, un
static void __init
lite5200_setup_cpu(void)
{
- struct mpc52xx_cdm __iomem *cdm;
struct mpc52xx_gpio __iomem *gpio;
struct mpc52xx_intr __iomem *intr;
- struct mpc52xx_xlb __iomem *xlb;
u32 port_config;
u32 intr_ctrl;
/* Map zones */
- cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
gpio = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE);
- xlb = ioremap(MPC52xx_PA(MPC52xx_XLB_OFFSET), MPC52xx_XLB_SIZE);
intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
- if (!cdm || !gpio || !xlb || !intr) {
- printk("lite5200.c: Error while mapping CDM/GPIO/XLB/INTR during"
- "lite5200_setup_cpu\n");
+ if (!gpio || !intr) {
+ printk(KERN_ERR __FILE__ ": "
+ "Error while mapping GPIO/INTR during "
+ "lite5200_setup_cpu\n");
goto unmap_regs;
}
- /* Use internal 48 Mhz */
- out_8(&cdm->ext_48mhz_en, 0x00);
- out_8(&cdm->fd_enable, 0x01);
- if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */
- out_be16(&cdm->fd_counters, 0x0001);
- else
- out_be16(&cdm->fd_counters, 0x5555);
-
/* Get port mux config */
port_config = in_be32(&gpio->port_config);
@@ -137,17 +124,13 @@ lite5200_setup_cpu(void)
port_config &= ~0x00007000; /* Differential mode - USB1 only */
port_config |= 0x00001000;
+ /* ATA CS is on csb_4/5 */
+ port_config &= ~0x03000000;
+ port_config |= 0x01000000;
+
/* Commit port config */
out_be32(&gpio->port_config, port_config);
- /* Configure the XLB Arbiter */
- out_be32(&xlb->master_pri_enable, 0xff);
- out_be32(&xlb->master_priority, 0x11111111);
-
- /* Enable ram snooping for 1GB window */
- out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_SNOOP);
- out_be32(&xlb->snoop_window, MPC52xx_PCI_TARGET_MEM | 0x1d);
-
/* IRQ[0-3] setup */
intr_ctrl = in_be32(&intr->ctrl);
intr_ctrl &= ~0x00ff0000;
@@ -163,9 +146,7 @@ lite5200_setup_cpu(void)
/* Unmap reg zone */
unmap_regs:
- if (cdm) iounmap(cdm);
if (gpio) iounmap(gpio);
- if (xlb) iounmap(xlb);
if (intr) iounmap(intr);
}
@@ -173,7 +154,8 @@ static void __init
lite5200_setup_arch(void)
{
/* CPU & Port mux setup */
- lite5200_setup_cpu();
+ mpc52xx_setup_cpu(); /* Generic */
+ lite5200_setup_cpu(); /* Platform specific */
#ifdef CONFIG_PCI
/* PCI Bridge setup */
diff --git a/arch/ppc/syslib/mpc52xx_setup.c b/arch/ppc/syslib/mpc52xx_setup.c
index 2ee48ce..ee6379b 100644
--- a/arch/ppc/syslib/mpc52xx_setup.c
+++ b/arch/ppc/syslib/mpc52xx_setup.c
@@ -24,6 +24,8 @@
#include <asm/pgtable.h>
#include <asm/ppcboot.h>
+#include <syslib/mpc52xx_pci.h>
+
extern bd_t __res;
static int core_mult[] = { /* CPU Frequency multiplier, taken */
@@ -216,6 +218,52 @@ mpc52xx_calibrate_decr(void)
tb_to_us = mulhwu_scale_factor(xlbfreq / divisor, 1000000);
}
+
+void __init
+mpc52xx_setup_cpu(void)
+{
+ struct mpc52xx_cdm __iomem *cdm;
+ struct mpc52xx_xlb __iomem *xlb;
+
+ /* Map zones */
+ cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
+ xlb = ioremap(MPC52xx_PA(MPC52xx_XLB_OFFSET), MPC52xx_XLB_SIZE);
+
+ if (!cdm || !xlb) {
+ printk(KERN_ERR __FILE__ ": "
+ "Error while mapping CDM/XLB during "
+ "mpc52xx_setup_cpu\n");
+ goto unmap_regs;
+ }
+
+ /* Use internal 48 Mhz */
+ out_8(&cdm->ext_48mhz_en, 0x00);
+ out_8(&cdm->fd_enable, 0x01);
+ if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */
+ out_be16(&cdm->fd_counters, 0x0001);
+ else
+ out_be16(&cdm->fd_counters, 0x5555);
+
+ /* Configure the XLB Arbiter priorities */
+ out_be32(&xlb->master_pri_enable, 0xff);
+ out_be32(&xlb->master_priority, 0x11111111);
+
+ /* Enable ram snooping for 1GB window */
+ out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_SNOOP);
+ out_be32(&xlb->snoop_window, MPC52xx_PCI_TARGET_MEM | 0x1d);
+
+ /* Disable XLB pipelining */
+ /* (cfr errate 292. We could do this only just before ATA PIO
+ transaction and re-enable it after ...) */
+ out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS);
+
+ /* Unmap reg zone */
+unmap_regs:
+ if (cdm) iounmap(cdm);
+ if (xlb) iounmap(xlb);
+}
+
+
int mpc52xx_match_psc_function(int psc_idx, const char *func)
{
struct mpc52xx_psc_func *cf = mpc52xx_psc_functions;
diff --git a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
index 6167f74..7e98428 100644
--- a/include/asm-ppc/mpc52xx.h
+++ b/include/asm-ppc/mpc52xx.h
@@ -355,6 +355,7 @@ struct mpc52xx_xlb {
u32 snoop_window; /* XLB + 0x70 */
};
+#define MPC52xx_XLB_CFG_PLDIS (1 << 31)
#define MPC52xx_XLB_CFG_SNOOP (1 << 15)
/* Clock Distribution control */
@@ -427,6 +428,9 @@ extern void mpc52xx_calibrate_decr(void)
extern void mpc52xx_find_bridges(void);
+extern void mpc52xx_setup_cpu(void);
+
+
/* Matching of PSC function */
struct mpc52xx_psc_func {
^ 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