* Re: ioremap and outb
From: Arnd Bergmann @ 2008-01-04 10:45 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <20080104102037.GA31627@mail.gnudd.com>
On Friday 04 January 2008, Alessandro Rubini wrote:
> > =A0 =A0 =A0 =A0 =A0addr=3Dioremap(base_addr,size); =A0 =A0 =A0 =A0 =A0/=
/ Remap to Mem mapped
>=20
> Yes.
In newer drivers that are specific to powerpc, it's often easier
to use the of_iomap() function to map a device, so you don't
have to calculate the base address manually from the device tree.
> > =A0 =A0 =A0 =A0 =A0out_8(addr) and in_8(addr);=20
>=20
> It should be right, although __raw_readb() and __raw_writeb() may
> suffice for you.
Actually not. While they may work, the __raw_* functions do not have
a specific meaning in device drivers. Depending on the I/O model, they
may or may not work on a given platform. The {in,out}_{8,{be,le}{16,32,64}}
functions however are defined to operate on local (not PCI) ioremapped
mmio devices, and are usually more efficient than the {read,write}{b,w,l,q}
variant you'd use on PCI devices.
Arnd <><
^ permalink raw reply
* Re: MPC8260ADS and linux-2.6
From: suja Baburaj @ 2008-01-04 11:22 UTC (permalink / raw)
To: Rune Torgersen; +Cc: Scott Wood, linuxppc-embedded
In-Reply-To: <DCEAAC0833DD314AB0B58112AD99B93B03D1682A@ismail.innsys.innovsys.com>
[-- Attachment #1: Type: text/plain, Size: 554 bytes --]
Hi,
The PQ2FADS support worked for MPC8260ADS.
Thanks to Rune and scott for the input.
-suja
> >
> > suja Baburaj wrote:
> > > I have an MPC8260ADS board with (eldk)linux-2.4.25 working
> > fine on it.
> > > Now i want to try linux-2.6.X on the board.
> >
> > There's no support for that specific board in mainstream 2.6
> > yet, but it
> > should be fairly simple to get it working using the
> > mpc8272ads support
> > as an example.
>
> There is support, but it is in arch/ppc not arch/powerpc
> (PQ2FADS support works for this board in arch/ppc)
>
[-- Attachment #2: Type: text/html, Size: 860 bytes --]
^ permalink raw reply
* RE: File system problem
From: mojtaba @ 2008-01-04 11:57 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <169c03cb0801031557r1efbd89fsd971533e04477daa@mail.gmail.com>
Hi,
Thank you all for your helps.
Today I tried to make the file system again using buildroot. This time I
included busybox to the packages for target system (Before that, I did =
not
include the busybox). Surprisingly the system boot correctly.
But, I do not want to use busybox. I already compiled coreutiles and I =
want
to put them on my target system. After building the root file system I =
tried
to replace those symbolic links to busybox(such as ls, cp, ...) with the
real commands from coreutiles but I got this error.
Freeing unused kernel memory: 76k init
missing file opeKernel panic - not syncing: Attempted to kill init!
rand
Try `/bin/Rebooting in 180 seconds..sh --help' for more information.
So, how can I use coreutils instead of busybox?
Regards,
Mojtaba
-----Original Message-----
From: jsamch@gmail.com [mailto:jsamch@gmail.com] On Behalf Of =
Jean-Samuel
Chenard
Sent: Friday, January 04, 2008 12:58 AM
To: linuxppc-embedded@ozlabs.org; kernelppc@gmail.com
Subject: RE: File system problem
> Message: 9
> Date: Thu, 3 Jan 2008 18:00:14 +0100
> From: "mojtaba"
>
> Actually, I removed the console and null created by buildroot and =
create
> them manually using make node. This time the system freezes at this =
point.
> "Freeing unused kernel memory: 76k init"
Hi Mojtaba,
I just want to comment on your observation that the file size in /dev
was zero. This is normal as the device files are 'special' since they
are a mean of abstracting the interface to the kernel. I had to read
the online book listed below before I could understand the inner
workings of those special files. If you plan on interfacing your FPGA
with the Linux Kernel, I suggest you read it too, as it is a very
insightful book:
http://lwn.net/Kernel/LDD3/
At this point, your system is not frozen, but your init script and
configuration files are probably not all correctly set. You might
need to read some documentation about buildroot to see what its init
scripts are trying to do.
You might be missing a library or symlink (I got that problem in my
attempt to build the BusyBox root filesystem from scratch). One way
to go at the problem is to pass the init=3D/bin/ash or something like
that to your kernel at the boot prompt (you could even make some
trivial 'hello world' program and pass it to the kernel as the init
process). This way, you can dive right into a shell or your program
and avoid init and its configuration.
After some copying of required libraries in /lib (I'm using uClibc)
and the creation of the required symbolic links, I got my Busybox root
filesystem working on my ML-310 board.
Good luck!
Regards,
Jean-Samuel
--=20
Ph.D. candidate
Integrated Microsystems Laboratory
McGill University, Montr=E9al, QC, CANADA
Web Page: http://chaos.ece.mcgill.ca
^ permalink raw reply
* Re: [alsa-devel] [PATCH] ASoC drivers for the Freescale MPC8610 SoC
From: Mark Brown @ 2008-01-04 13:39 UTC (permalink / raw)
To: Timur Tabi, Grant Likely, linuxppc-dev, alsa-devel
In-Reply-To: <20080103234725.GD12883@localhost.localdomain>
On Fri, Jan 04, 2008 at 10:47:25AM +1100, David Gibson wrote:
> On Thu, Jan 03, 2008 at 12:16:19PM -0600, Timur Tabi wrote:
> > I'm no expert on this, but I think from the PowerPC point-of-view,
> > the *ideal* situation would be if the ASoC fabric driver were
> > generic, maybe even part of ASoC itself, and everything it needed
> > could be obtained from the device tree.
> Nice idea in principle, and may be the way to go ultimately, but very
> tricky in practice. The whole reason the fabric driver concept exists
> (from other archs) is that there are an awful lot of variants on how
> to wire the sound components together. Devising a way of expressing
> those connections in the device tree that's sufficient will be very
> curly. Then we'd have to build the fabric driver that can parse and
> process them all.
Yes, there's an issue with complexity here. Some of the individual
components are going to have quite a lot of different things to
configure by themselves even for static use and the choices made may
depend on the usage at run time rather than being a static property of
the hardware. It's also more than just connections - many machine
drivers will provide control for components like analogue switches or
simple amplifiers controlled through GPIO lines or memory mapped
registers (these are generally specific to the board).
As a result I would expect that you will always have systems using
platform based drivers. I don't think that this is a bad thing -
something that can completely replace them would be able to do anything
that can be done in C in the kernel.
> And then, people will no doubt produce device trees
> with errors in the connection information, so we'll still need
> platform-specific workarounds.
The other concern with this is that it risks turning the interface to
the codec and controller drivers into an ABI which isn't expected at the
minute and might cause problems in the future. At the minute the
drivers export constants to their users defining the parameters they
can configure and (for things like source selection) the possible
values. These can currently be changed at will and there's no great
consistency in their values between drivers.
There would also be difficulties in writing the device tree - without
the symbolic names you're going to end up with strings of numeric
constants in the device tree which are not going to be terribly readable
and will be error prone.
> If we want sound working any time soon, we'll want to stick with the
> platform based fabric drivers for the time being.
Like I say, I would expect that you're always going to want to have
platform based drivers. Even if a given board can be represented in a
device tree some users will find it more straightforward or convenient
to write C code for their platform and have the device tree specify more
basic configuration options that correspond to the things they want to
vary between boards.
^ permalink raw reply
* [PATCH] [POWERPC] 4xx: Add EMAC support to Kilauea defconfig
From: Stefan Roese @ 2008-01-04 14:00 UTC (permalink / raw)
To: linuxppc-dev
Somehow the EMAC support was dropped (or never really added) to the
Kilauea defconfig file. This patch finally adds EMAC support.
Signed-off-by: Stefan Roese <sr@denx.de>
---
arch/powerpc/configs/kilauea_defconfig | 23 +++++++++++++++++++++--
1 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/configs/kilauea_defconfig b/arch/powerpc/configs/kilauea_defconfig
index c86e756..8dca3d4 100644
--- a/arch/powerpc/configs/kilauea_defconfig
+++ b/arch/powerpc/configs/kilauea_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.24-rc6
-# Mon Dec 24 11:18:12 2007
+# Thu Jan 3 14:21:31 2008
#
# CONFIG_PPC64 is not set
@@ -453,9 +453,28 @@ CONFIG_NETDEVICES=y
# CONFIG_VETH is not set
# CONFIG_IP1000 is not set
# CONFIG_ARCNET is not set
-# CONFIG_NET_ETHERNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_IBM_NEW_EMAC=y
+CONFIG_IBM_NEW_EMAC_RXB=256
+CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
CONFIG_IBM_NEW_EMAC_RGMII=y
+# CONFIG_IBM_NEW_EMAC_TAH is not set
CONFIG_IBM_NEW_EMAC_EMAC4=y
+# CONFIG_NET_PCI is not set
+# CONFIG_B44 is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_TR is not set
--
1.5.4.rc2
^ permalink raw reply related
* Re: [PATCH 1/3] Add yyerrorf() for formatted error messages.
From: Jon Loeliger @ 2008-01-04 14:30 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <477D73B6.1070108@freescale.com>
So, like, the other day Scott Wood mumbled:
>
> I forgot to tag them as such, but these are of course dtc patches and
> not Linux patches.
All three applied (to DTC :-)).
Will you follow up with a patch for /bininc/ or /bin-include/
as well now? (I'm fine with either, and I forget where David's
preference there landed.)
Thanks,
jdl
^ permalink raw reply
* Re: Outstanding DTC patches?
From: Jon Loeliger @ 2008-01-04 14:38 UTC (permalink / raw)
To: David Gibson; +Cc: linuxppc-dev@ozlabs.org
In-Reply-To: <20080104024324.GA4326@localhost.localdomain>
So, like, the other day David Gibson mumbled:
> Ah, I think I sent it by private mail, so it won't be in patchwork.
> Here you are:
Ah, that explains it.
> dtc/libfdt: Add README clarifying licensing
>
> The fact the dtc are distributed together, but have different licenses
> can be a bit confusing. Several people have enquired as to what the
> deal is with the libfdt licensing, so this patch adds a README
> clarifying the situation with a rationale.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
After correcting the log-message English a bit, it was applied.
The fact that the dtc and libfdt are distributed together, but have
different licenses, can be a bit confusing. Several people have
enquired as to what the deal is with the libfdt licensing, so this
patch adds a README clarifying the situation with a rationale.
To be in agreement in the record, I too signed off on that patch.
Objections to either, please let me know!
Thanks,
jdl
^ permalink raw reply
* Re: [PATCH 1/3] Add yyerrorf() for formatted error messages.
From: Scott Wood @ 2008-01-04 16:55 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-dev
In-Reply-To: <E1JAnYr-0003hT-06@jdl.com>
On Fri, Jan 04, 2008 at 08:30:12AM -0600, Jon Loeliger wrote:
> All three applied (to DTC :-)).
>
> Will you follow up with a patch for /bininc/ or /bin-include/
> as well now? (I'm fine with either, and I forget where David's
> preference there landed.)
Yes, probably sometime today.
-Scott
^ permalink raw reply
* Re: [PATCh v3] powerpc: add hugepagesz boot-time parameter
From: Jon Tollefson @ 2008-01-04 20:00 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Adam Litke, mel, David Gibson, linuxppc-dev, Paul Mackerras,
csnook
In-Reply-To: <200801040034.25329.arnd@arndb.de>
Arnd Bergmann wrote:
> We started discussing this in v1, but the discussion got sidetracked:
> Is there a technical reason why you don't also allow 1M pages, which
> may be useful in certain scenarios?
>
No, it was mostly a matter of the time I have had and machines easily
available to me for testing. I don't know of a technical reason that
would prevent supporting 1M huge pages, but would want the tests in the
libhugetlbfs suite to pass, etc.
> On the Cell/B.E. platforms (IBM/Mercury blades, Toshiba Celleb, PS3), the
> second large page size is an option that can be set in a HID SPR
> to either 64KB or 1MB. Unfortunately, we can't do these two simultaneously,
> but the firmware can change the default and put it into the device tree,
> or you could have the kernel override the firmware settings.
>
> Going a lot further, do you have plans for a fully dynamic hugepage size,
> e.g. using a mount option for hugetlbfs? I can see that as rather useful,
> but at the same time it's probably much more complicated than the boot time
> option.
>
Eventually we will want to support dynamic huge page sizes. This is
already being looked into. In the meantime we can have some flexibility
with a boot-time parameter though.
> Arnd <><
>
Jon
^ permalink raw reply
* Control not branching to the instruction present at resetvec i.e 0xfffffffc
From: ravi.rao @ 2008-01-04 20:58 UTC (permalink / raw)
To: linuxlink-help; +Cc: Miki.Groftisza, linuxppc-embedded
In-Reply-To: <14612548.post@talk.nabble.com>
[-- Attachment #1: Type: text/plain, Size: 1458 bytes --]
Hi All,
We have a custom target board based on PPC-EP405. We just got the
board from the hardware team .I connected the board to BDI200 and powered
it on.
The control came to the resetvec address which is 0xfffffffc. I was able
to read and write to flash. So I erased the flash and burnt the bootloader
into flash from 0xfffc0000.
I verified that the instruction at 0xfffffffc is 4bfc2104 whicis actually
a branch to 0xfffc2100. Also a memory dump of 0xfffc2100 shows the correct
code. This proved that
the uboot bootloader was burnt properly.
Now when I reset the board the control never reaches 0xfffc2100 i.e for
some reason the code at the resetvec is not getting executed. Any help or
pointers to resolve this is greatly appreciated.
Thanks,
Ravishankar Govindarao
RFL Electronics Inc.
E-mail : Ravi.Rao@rflelect.com
Voice: 973.334.3100 Ext. 233
Fax: 973.334.3863
CONFIDENTIALITY NOTE
This e-mail, including any attachments, may contain confidential and/or
legally privileged information. The Information is intended only for the
use of the individual or entity named on this e-mail . If you are not the
intended recipient, you are hereby notified that any disclosure, copying,
distribution, or the taking of any action in reliance on the contents of
this transmitted Information is strictly prohibited. Further, if you are
not the intended recipient, please notify us by return e-mail and delete
the Information promptly.
[-- Attachment #2: Type: text/html, Size: 2192 bytes --]
^ permalink raw reply
* [PATCH 2/3] Handle absolute pathnames correctly in dtc_open_file.
From: Scott Wood @ 2008-01-04 21:10 UTC (permalink / raw)
To: jdl; +Cc: linuxppc-dev
Also, free file->dir when freeing file.
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
srcpos.c | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/srcpos.c b/srcpos.c
index 7340c33..7a0c47e 100644
--- a/srcpos.c
+++ b/srcpos.c
@@ -86,6 +86,16 @@ struct dtc_file *dtc_open_file(const char *fname,
return file;
}
+ if (fname[0] == '/') {
+ file->file = fopen(fname, "r");
+
+ if (!file->file)
+ goto out;
+
+ file->name = strdup(fname);
+ return file;
+ }
+
if (!search)
search = &default_search;
@@ -100,6 +110,7 @@ struct dtc_file *dtc_open_file(const char *fname,
}
out:
+ free((void *)file->dir);
free(file);
return NULL;
}
@@ -109,5 +120,6 @@ void dtc_close_file(struct dtc_file *file)
if (fclose(file->file))
die("Error closing \"%s\": %s\n", file->name, strerror(errno));
+ free((void *)file->dir);
free(file);
}
--
1.5.3
^ permalink raw reply related
* [PATCH 1/3] Add support for binary includes.
From: Scott Wood @ 2008-01-04 21:10 UTC (permalink / raw)
To: jdl; +Cc: linuxppc-dev
A property's data can be populated with a file's contents
as follows:
node {
prop = /incbin/("path/to/data");
};
A subset of a file can be included by passing start and size parameters.
For example, to include bytes 8 through 23:
node {
prop = /incbin/("path/to/data", 8, 16);
};
As with /include/, non-absolute paths are looked for in the directory
of the source file that includes them.
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
Makefile | 2 +-
data.c | 37 ++++++++++++++++++++++++++++++++++++-
dtc-lexer.l | 7 +++++++
dtc-parser.y | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
dtc.h | 5 +++++
5 files changed, 98 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
index 6e07862..578d8c1 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@ LOCAL_VERSION =
CONFIG_LOCALVERSION =
CPPFLAGS = -I libfdt
-CFLAGS = -Wall -g -Os
+CFLAGS = -Wall -g -Os -D_FILE_OFFSET_BITS=64
BISON = bison
LEX = flex
diff --git a/data.c b/data.c
index a94718c..f9464bf 100644
--- a/data.c
+++ b/data.c
@@ -19,6 +19,7 @@
*/
#include "dtc.h"
+#include "srcpos.h"
void data_free(struct data d)
{
@@ -189,7 +190,41 @@ struct data data_copy_file(FILE *f, size_t len)
d = data_grow_for(empty_data, len);
d.len = len;
- fread(d.val, len, 1, f);
+ if (fread(d.val, len, 1, f) != 1) {
+ yyerrorf("Couldn't read %zu bytes from file: %s",
+ len, feof(f) ? "end-of-file" : strerror(errno));
+ return empty_data;
+ }
+
+ return d;
+}
+
+struct data data_copy_file_all(FILE *f)
+{
+ char buf[4096];
+ struct data d = empty_data;
+
+ while (1) {
+ size_t ret = fread(buf, 1, sizeof(buf), f);
+ if (ret == 0) {
+ if (!feof(f))
+ yyerrorf("Error reading file: %s", strerror(errno));
+
+ break;
+ }
+
+ assert(ret <= sizeof(buf));
+
+ d = data_grow_for(d, ret);
+ memcpy(d.val + d.len, buf, ret);
+
+ if (d.len + ret < d.len) {
+ yyerror("Binary include too large");
+ break;
+ }
+
+ d.len += ret;
+ }
return d;
}
diff --git a/dtc-lexer.l b/dtc-lexer.l
index bfb996e..7670aca 100644
--- a/dtc-lexer.l
+++ b/dtc-lexer.l
@@ -190,6 +190,13 @@ static int dts_version; /* = 0 */
return DT_PROPNODENAME;
}
+"/incbin/" {
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ DPRINT("Binary Include\n");
+ return DT_INCBIN;
+ }
+
<*>[[:space:]]+ /* eat whitespace */
<*>"/*"([^*]|\*+[^*/])*\*+"/" {
diff --git a/dtc-parser.y b/dtc-parser.y
index da7f6f5..f50f2f0 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -21,6 +21,8 @@
%locations
%{
+#include <stdio.h>
+
#include "dtc.h"
#include "srcpos.h"
@@ -47,6 +49,7 @@ extern int treesource_error;
struct node *node;
struct node *nodelist;
struct reserve_info *re;
+ struct range range;
}
%token DT_V1
@@ -59,6 +62,7 @@ extern int treesource_error;
%token <data> DT_STRING
%token <labelref> DT_LABEL
%token <labelref> DT_REF
+%token DT_INCBIN
%type <data> propdata
%type <data> propdataprefix
@@ -79,6 +83,7 @@ extern int treesource_error;
%type <node> subnode
%type <nodelist> subnodes
%type <labelref> label
+%type <range> mayberange
%%
@@ -197,12 +202,56 @@ propdata:
{
$$ = data_add_marker($1, REF_PATH, $2);
}
+ | propdataprefix DT_INCBIN '(' DT_STRING mayberange ')'
+ {
+ struct search_path path = { srcpos_file->dir, NULL, NULL };
+ struct dtc_file *file = dtc_open_file($4.val, &path);
+
+ if (!file) {
+ yyerrorf("Cannot open file \"%s\": %s",
+ $4.val, strerror(errno));
+ } else {
+ struct data d = empty_data;
+
+ if ($5.len >= 0) {
+ if (fseek(file->file, $5.start, SEEK_SET) == 0)
+ d = data_copy_file(file->file, $5.len);
+ else
+ yyerrorf("Couldn't seek to offset %llu in \"%s\": %s",
+ (unsigned long long)$5.start,
+ $4.val, strerror(errno));
+ } else {
+ d = data_copy_file_all(file->file);
+ }
+
+ $$ = data_merge($1, d);
+ dtc_close_file(file);
+ }
+ }
| propdata DT_LABEL
{
$$ = data_add_marker($1, LABEL, $2);
}
;
+mayberange:
+ /* empty */
+ {
+ $$.len = -1;
+ }
+ | ',' addr ',' addr
+ {
+ $$.start = $2;
+ $$.len = $4;
+
+ if ($$.len != $4) {
+ yyerrorf("Length %llu is too large",
+ (unsigned long long)$4);
+ $$.len = -1;
+ }
+ }
+ ;
+
propdataprefix:
/* empty */
{
diff --git a/dtc.h b/dtc.h
index cba9d28..509fbc9 100644
--- a/dtc.h
+++ b/dtc.h
@@ -122,6 +122,10 @@ struct data {
struct marker *markers;
};
+struct range {
+ off_t start;
+ int len;
+};
#define empty_data ((struct data){ /* all .members = 0 or NULL */ })
@@ -138,6 +142,7 @@ struct data data_grow_for(struct data d, int xlen);
struct data data_copy_mem(const char *mem, int len);
struct data data_copy_escape_string(const char *s, int len);
struct data data_copy_file(FILE *f, size_t len);
+struct data data_copy_file_all(FILE *f);
struct data data_append_data(struct data d, const void *p, int len);
struct data data_insert_at_marker(struct data d, struct marker *m,
--
1.5.3
^ permalink raw reply related
* [PATCH 3/3] Remove \n from yyerror() call.
From: Scott Wood @ 2008-01-04 21:10 UTC (permalink / raw)
To: jdl; +Cc: linuxppc-dev
The \n is provided by yyerror().
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
dtc-parser.y | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/dtc-parser.y b/dtc-parser.y
index f50f2f0..3a24d14 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -332,7 +332,7 @@ subnodes:
}
| subnode propdef
{
- yyerror("syntax error: properties must precede subnodes\n");
+ yyerror("syntax error: properties must precede subnodes");
YYERROR;
}
;
--
1.5.3
^ permalink raw reply related
* Re: [PATCh v3] powerpc: add hugepagesz boot-time parameter
From: Arnd Bergmann @ 2008-01-04 23:03 UTC (permalink / raw)
To: linuxppc-dev
Cc: Jon Tollefson, Adam Litke, mel, David Gibson, Paul Mackerras,
csnook
In-Reply-To: <477E9073.1050900@linux.vnet.ibm.com>
On Friday 04 January 2008, Jon Tollefson wrote:
> Arnd Bergmann wrote:
> > We started discussing this in v1, but the discussion got sidetracked:
> > Is there a technical reason why you don't also allow 1M pages, which
> > may be useful in certain scenarios?
> > =A0=20
> No, it was mostly a matter of the time I have had and machines easily
> available to me for testing. =A0I don't know of a technical reason that
> would prevent supporting 1M huge pages, but would want the tests in the
> libhugetlbfs suite to pass, etc.
Ok. Do you think the kernel should be able to change the page size settings
in that case, or should we rely on whatever the firmware tells us it has
configured already?
Arnd <><
^ permalink raw reply
* [PATCH] enable built-in networking for Sequoia defconfig
From: Hollis Blanchard @ 2008-01-04 23:26 UTC (permalink / raw)
To: Josh Boyer; +Cc: linuxppc-dev
Enable EMAC driver for Sequoia (and while we're in there, disable
Macintosh drivers for Sequoia and Bamboo).
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
diff --git a/arch/powerpc/configs/bamboo_defconfig b/arch/powerpc/configs/bamboo_defconfig
--- a/arch/powerpc/configs/bamboo_defconfig
+++ b/arch/powerpc/configs/bamboo_defconfig
@@ -372,9 +372,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
-CONFIG_MACINTOSH_DRIVERS=y
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
diff --git a/arch/powerpc/configs/sequoia_defconfig b/arch/powerpc/configs/sequoia_defconfig
--- a/arch/powerpc/configs/sequoia_defconfig
+++ b/arch/powerpc/configs/sequoia_defconfig
@@ -446,9 +446,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
-CONFIG_MACINTOSH_DRIVERS=y
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
@@ -459,10 +457,28 @@ CONFIG_NETDEVICES=y
# CONFIG_VETH is not set
# CONFIG_IP1000 is not set
# CONFIG_ARCNET is not set
-# CONFIG_NET_ETHERNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_IBM_NEW_EMAC=y
+CONFIG_IBM_NEW_EMAC_RXB=128
+CONFIG_IBM_NEW_EMAC_TXB=64
+CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+# CONFIG_IBM_NEW_EMAC_DEBUG is not set
CONFIG_IBM_NEW_EMAC_ZMII=y
CONFIG_IBM_NEW_EMAC_RGMII=y
+# CONFIG_IBM_NEW_EMAC_TAH is not set
CONFIG_IBM_NEW_EMAC_EMAC4=y
+# CONFIG_NET_PCI is not set
+# CONFIG_B44 is not set
CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
^ permalink raw reply
* Re: [PATCH] ASoC drivers for the Freescale MPC8610 SoC
From: Timur Tabi @ 2008-01-05 2:35 UTC (permalink / raw)
To: Grant Likely; +Cc: Scott Wood, linuxppc-dev, alsa-devel
In-Reply-To: <fa686aa40801031113od68e2a3m6cb60b8fa6f26c17@mail.gmail.com>
Grant Likely wrote:
> On 1/3/08, Scott Wood <scottwood@freescale.com> wrote:
>> Grant Likely wrote:
>>> On 1/3/08, Timur Tabi <timur@freescale.com> wrote:
>>>> Grant Likely wrote:
>>>>
>>>>> Why not be a child of the i2c bus with a phandle to the ssi bus?
>>>> Because when I probe the SSI node, I want to know what the attached codec is.
>>>> So if anything, I would need a pointer from the SSI bus *to* the respective
>>>> child on the I2C bus.
>>> That's fine too (it's what is done with Ethernet PHYs). My preference
>>> is the other way around, but it's not a big issue in this case.
>> I'd just link in both directions, and let software follow it in
>> whichever direction it prefers.
>
> Gah! Don't do that! Then you need to maintain both directions in the
> dts file.
So? What's wrong with that?
> Software is good at generating reverse mappings.
What software would that be? Currently, there is no software that will do
that? Or are you saying that you want my driver to search the entire device
tree until it finds the reverse mapping? I don't think *that* is a good idea.
> Don't put
> that burden on the dts author.
As the DTS author in question, I hereby declare that such a requirement is not
a burden in the slightest. Thank you.
--
Timur Tabi
Linux Kernel Developer @ Freescale
^ permalink raw reply
* Re: [alsa-devel] [PATCH] ASoC drivers for the Freescale MPC8610 SoC
From: Timur Tabi @ 2008-01-05 2:39 UTC (permalink / raw)
To: Timur Tabi, Jon Smirl, Liam Girdwood, alsa-devel, linuxppc-dev
In-Reply-To: <20080103235156.GE12883@localhost.localdomain>
David Gibson wrote:
> And what distinction are you drawing between "first" and "second"
> here?
Oh, that's an easy one: The CS4270 can work without an I2C or SPI connection,
but it will never work without an I2S connection.
> Why would the I2S need to scan for codecs? Wouldn't it be up to the
> codec driver to register with I2S?
Not in ASoC V1. The codec driver registers with ASoC, but the actual
connection to other devices (e.g. the I2S driver) is done either in the I2S
driver or in the fabric driver, depending on your mood. And that connection
is done via a pointer to a structure in the codec driver.
--
Timur Tabi
Linux Kernel Developer @ Freescale
^ permalink raw reply
* Re: [alsa-devel] [PATCH] ASoC drivers for the Freescale MPC8610 SoC
From: Timur Tabi @ 2008-01-05 2:43 UTC (permalink / raw)
To: Jon Smirl, linuxppc-dev, alsa-devel
In-Reply-To: <20080103230004.GA18709@sirena.org.uk>
Mark Brown wrote:
> Each individual call to set_sysclk() only takes three parameters but it
> can be called repeatedly and some configurations are going to require
> this.
In other words, ...
clock1 = <0, bb8000>
clock2 = <1, 653230>
clock23 = <0, ab2372>
> and of course the ordering matters.
Ok, you got me there. But then, isn't this just another example where the
device tree is incapable of describing a complex configuration, and so we need
a platform driver?
> Indeed. Providing the device tree stuff doesn't get set in stone I'm
> not sure we need to nail this down perfectly for ASoC v1 when we're
> running into trouble working around it.
I definitely agree with that. I'll be the first to admit that this driver,
much like ASoC V1, is a prototype.
--
Timur Tabi
Linux Kernel Developer @ Freescale
^ permalink raw reply
* [PATCH] i2c-ibm_iic driver
From: Sean MacLennan @ 2008-01-05 2:57 UTC (permalink / raw)
To: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 298 bytes --]
I converted the i2c-ibm_iic driver from an ocp driver to an of_platform
driver. Since this driver is in the kernel.org kernel, should I rename
it and keep the old one around? I notice this was done with the emac
network driver.
This driver is required for the taco platform.
Cheers,
Sean
[-- Attachment #2: i2c-patch --]
[-- Type: text/plain, Size: 7545 bytes --]
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index c466c6c..e9e1493 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -241,7 +241,6 @@ config I2C_PIIX4
config I2C_IBM_IIC
tristate "IBM PPC 4xx on-chip I2C interface"
- depends on IBM_OCP
help
Say Y here if you want to use IIC peripheral found on
embedded IBM PPC 4xx based systems.
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 9b43ff7..838006f 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -3,6 +3,10 @@
*
* Support for the IIC peripheral on IBM PPC 4xx
*
+ * Copyright (c) 2008 PIKA Technologies
+ * Sean MacLennan <smaclennan@pikatech.com>
+ * Converted to an of_platform_driver.
+ *
* Copyright (c) 2003, 2004 Zultys Technologies.
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
@@ -39,12 +43,11 @@
#include <asm/io.h>
#include <linux/i2c.h>
#include <linux/i2c-id.h>
-#include <asm/ocp.h>
-#include <asm/ibm4xx.h>
+#include <linux/of_platform.h>
#include "i2c-ibm_iic.h"
-#define DRIVER_VERSION "2.1"
+#define DRIVER_VERSION "2.2"
MODULE_DESCRIPTION("IBM IIC driver v" DRIVER_VERSION);
MODULE_LICENSE("GPL");
@@ -660,50 +663,58 @@ static inline u8 iic_clckdiv(unsigned int opb)
/*
* Register single IIC interface
*/
-static int __devinit iic_probe(struct ocp_device *ocp){
-
+static int __devinit iic_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ static int index = 0;
+ struct device_node *np = ofdev->node;
struct ibm_iic_private* dev;
struct i2c_adapter* adap;
- struct ocp_func_iic_data* iic_data = ocp->def->additions;
+ const u32 *addrp, *freq;
+ u64 addr;
int ret;
-
- if (!iic_data)
- printk(KERN_WARNING"ibm-iic%d: missing additional data!\n",
- ocp->def->index);
if (!(dev = kzalloc(sizeof(*dev), GFP_KERNEL))) {
- printk(KERN_CRIT "ibm-iic%d: failed to allocate device data\n",
- ocp->def->index);
+ printk(KERN_CRIT "ibm-iic: failed to allocate device data\n");
return -ENOMEM;
}
- dev->idx = ocp->def->index;
- ocp_set_drvdata(ocp, dev);
-
- if (!request_mem_region(ocp->def->paddr, sizeof(struct iic_regs),
- "ibm_iic")) {
+ dev->idx = index++;
+
+ dev_set_drvdata(&ofdev->dev, dev);
+
+ if((addrp = of_get_address(np, 0, NULL, NULL)) == NULL ||
+ (addr = of_translate_address(np, addrp)) == OF_BAD_ADDR) {
+ printk(KERN_CRIT "ibm-iic%d: Unable to get iic address\n",
+ dev->idx);
ret = -EBUSY;
goto fail1;
}
- if (!(dev->vaddr = ioremap(ocp->def->paddr, sizeof(struct iic_regs)))){
+ if (!(dev->vaddr = ioremap(addr, sizeof(struct iic_regs)))){
printk(KERN_CRIT "ibm-iic%d: failed to ioremap device registers\n",
dev->idx);
ret = -ENXIO;
- goto fail2;
+ goto fail1;
}
init_waitqueue_head(&dev->wq);
- dev->irq = iic_force_poll ? -1 : ocp->def->irq;
- if (dev->irq >= 0){
+ if(iic_force_poll)
+ dev->irq = -1;
+ else if((dev->irq = irq_of_parse_and_map(np, 0)) == NO_IRQ) {
+ printk(KERN_ERR __FILE__ ": irq_of_parse_and_map failed\n");
+ dev->irq = -1;
+ }
+
+ if (dev->irq >= 0) {
/* Disable interrupts until we finish initialization,
assumes level-sensitive IRQ setup...
*/
iic_interrupt_mode(dev, 0);
- if (request_irq(dev->irq, iic_handler, 0, "IBM IIC", dev)){
+ if(request_irq(dev->irq, iic_handler, 0, "IBM IIC", dev)){
printk(KERN_ERR "ibm-iic%d: request_irq %d failed\n",
- dev->idx, dev->irq);
+ dev->idx, dev->irq);
/* Fallback to the polling mode */
dev->irq = -1;
}
@@ -711,23 +722,30 @@ static int __devinit iic_probe(struct ocp_device *ocp){
if (dev->irq < 0)
printk(KERN_WARNING "ibm-iic%d: using polling mode\n",
- dev->idx);
+ dev->idx);
/* Board specific settings */
- dev->fast_mode = iic_force_fast ? 1 : (iic_data ? iic_data->fast_mode : 0);
+ dev->fast_mode = iic_force_fast ? 1 : 0;
- /* clckdiv is the same for *all* IIC interfaces,
- * but I'd rather make a copy than introduce another global. --ebs
+ /* clckdiv is the same for *all* IIC interfaces, but I'd rather
+ * make a copy than introduce another global. --ebs
*/
- dev->clckdiv = iic_clckdiv(ocp_sys_info.opb_bus_freq);
+ if((freq = of_get_property(np, "clock-frequency", NULL)) == NULL &&
+ (freq = of_get_property(np->parent, "clock-frequency", NULL)) == NULL) {
+ printk(KERN_CRIT "ibm-iic%d: Unable to get bus frequency\n", dev->idx);
+ ret = -EBUSY;
+ goto fail;
+ }
+
+ dev->clckdiv = iic_clckdiv(*freq);
DBG("%d: clckdiv = %d\n", dev->idx, dev->clckdiv);
-
+
/* Initialize IIC interface */
iic_dev_init(dev);
/* Register it with i2c layer */
adap = &dev->adap;
- adap->dev.parent = &ocp->dev;
+ adap->dev.parent = &ofdev->dev;
strcpy(adap->name, "IBM IIC");
i2c_set_adapdata(adap, dev);
adap->id = I2C_HW_OCP;
@@ -737,13 +755,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
adap->client_unregister = NULL;
adap->timeout = 1;
adap->retries = 1;
-
- /*
- * If "dev->idx" is negative we consider it as zero.
- * The reason to do so is to avoid sysfs names that only make
- * sense when there are multiple adapters.
- */
- adap->nr = dev->idx >= 0 ? dev->idx : 0;
+ adap->nr = dev->idx;
if ((ret = i2c_add_numbered_adapter(adap)) < 0) {
printk(KERN_CRIT "ibm-iic%d: failed to register i2c adapter\n",
@@ -763,20 +775,19 @@ fail:
}
iounmap(dev->vaddr);
-fail2:
- release_mem_region(ocp->def->paddr, sizeof(struct iic_regs));
fail1:
- ocp_set_drvdata(ocp, NULL);
- kfree(dev);
+ dev_set_drvdata(&ofdev->dev, NULL);
+ kfree(dev);
return ret;
}
/*
* Cleanup initialized IIC interface
*/
-static void __devexit iic_remove(struct ocp_device *ocp)
+static int __devexit iic_remove(struct of_device *ofdev)
{
- struct ibm_iic_private* dev = (struct ibm_iic_private*)ocp_get_drvdata(ocp);
+ struct ibm_iic_private* dev = (struct ibm_iic_private*)dev_get_drvdata(&ofdev->dev);
+
BUG_ON(dev == NULL);
if (i2c_del_adapter(&dev->adap)){
printk(KERN_CRIT "ibm-iic%d: failed to delete i2c adapter :(\n",
@@ -793,41 +804,37 @@ static void __devexit iic_remove(struct ocp_device *ocp)
free_irq(dev->irq, dev);
}
iounmap(dev->vaddr);
- release_mem_region(ocp->def->paddr, sizeof(struct iic_regs));
kfree(dev);
}
+
+ return 0;
}
-static struct ocp_device_id ibm_iic_ids[] __devinitdata =
+
+static struct of_device_id ibm_iic_match[] =
{
- { .vendor = OCP_VENDOR_IBM, .function = OCP_FUNC_IIC },
- { .vendor = OCP_VENDOR_INVALID }
+ { .type = "i2c", .compatible = "ibm,iic", },
+ {}
};
-MODULE_DEVICE_TABLE(ocp, ibm_iic_ids);
-
-static struct ocp_driver ibm_iic_driver =
+static struct of_platform_driver ibm_iic_driver =
{
- .name = "iic",
- .id_table = ibm_iic_ids,
+ .name = "ibm-iic",
+ .match_table = ibm_iic_match,
+
.probe = iic_probe,
- .remove = __devexit_p(iic_remove),
-#if defined(CONFIG_PM)
- .suspend = NULL,
- .resume = NULL,
-#endif
+ .remove = iic_remove,
};
-static int __init iic_init(void)
+static int __init ibm_iic_init(void)
{
printk(KERN_INFO "IBM IIC driver v" DRIVER_VERSION "\n");
- return ocp_register_driver(&ibm_iic_driver);
+ return of_register_platform_driver(&ibm_iic_driver);
}
+module_init(ibm_iic_init);
-static void __exit iic_exit(void)
+static void __exit ibm_iic_exit(void)
{
- ocp_unregister_driver(&ibm_iic_driver);
+ of_unregister_platform_driver(&ibm_iic_driver);
}
-
-module_init(iic_init);
-module_exit(iic_exit);
+module_exit(ibm_iic_exit);
^ permalink raw reply related
* [patch 0/3] PS3 logical performance monitor patches for 2.6.25
From: Geoff Levand @ 2008-01-05 3:12 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
Paul,
This is a small set of patches that adds support for the PS3's logical
performance monitor.
The logical performance monitor is a hypervisor abstraction that provides
access to the Cell processor's performance monitoring features needed by
profilers such as oprofile and perfmon.
Please apply for 2.6.25.
[1/3] PS3: Add logical performance monitor repository routines
[2/3] PS3: Add logical performance monitor device support
[3/3] PS3: Add logical performance monitor driver support
-Geoff
--
^ permalink raw reply
* [patch 1/3] PS3: Add logical performance monitor repository routines
From: Geoff Levand @ 2008-01-05 3:12 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev, Takashi Yamamoto
In-Reply-To: <20080105003019.595703814@am.sony.com>
From: Takashi Yamamoto <Takashi02_Yamamoto@hq.scei.sony.co.jp>
Add repository routines for the PS3 Logical Performance Monitor (lpm).
Signed-off-by: Takashi Yamamoto <Takashi02_Yamamoto@hq.scei.sony.co.jp>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
arch/powerpc/platforms/ps3/platform.h | 7 ++++
arch/powerpc/platforms/ps3/repository.c | 48 ++++++++++++++++++++++++++++++++
2 files changed, 54 insertions(+), 1 deletion(-)
--- a/arch/powerpc/platforms/ps3/platform.h
+++ b/arch/powerpc/platforms/ps3/platform.h
@@ -189,7 +189,7 @@ int ps3_repository_read_stor_dev_region(
/* repository pu and memory info */
int ps3_repository_read_num_pu(unsigned int *num_pu);
-int ps3_repository_read_ppe_id(unsigned int *pu_index, unsigned int *ppe_id);
+int ps3_repository_read_pu_id(unsigned int pu_index, u64 *pu_id);
int ps3_repository_read_rm_base(unsigned int ppe_id, u64 *rm_base);
int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size);
int ps3_repository_read_region_total(u64 *region_total);
@@ -203,6 +203,11 @@ int ps3_repository_read_be_node_id(unsig
int ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq);
int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq);
+/* repository performance monitor info */
+
+int ps3_repository_read_lpm_privileges(unsigned int be_index, u64 *lpar,
+ u64 *rights);
+
/* repository 'Other OS' area */
int ps3_repository_read_boot_dat_addr(u64 *lpar_addr);
--- a/arch/powerpc/platforms/ps3/repository.c
+++ b/arch/powerpc/platforms/ps3/repository.c
@@ -902,6 +902,54 @@ int ps3_repository_read_be_tb_freq(unsig
: ps3_repository_read_tb_freq(node_id, tb_freq);
}
+int ps3_repository_read_lpm_privileges(unsigned int be_index, u64 *lpar,
+ u64 *rights)
+{
+ int result;
+ u64 node_id;
+
+ *lpar = 0;
+ *rights = 0;
+ result = ps3_repository_read_be_node_id(be_index, &node_id);
+ return result ? result
+ : read_node(PS3_LPAR_ID_PME,
+ make_first_field("be", 0),
+ node_id,
+ make_field("lpm", 0),
+ make_field("priv", 0),
+ lpar, rights);
+}
+
+int ps3_repository_read_num_pu(unsigned int *num_pu)
+{
+ int result;
+ u64 v1;
+
+ v1 = 0;
+ result = read_node(PS3_LPAR_ID_CURRENT,
+ make_first_field("bi", 0),
+ make_field("pun", 0),
+ 0, 0,
+ &v1, NULL);
+ *num_pu = v1;
+ return result;
+}
+
+int ps3_repository_read_pu_id(unsigned int pu_index, u64 *pu_id)
+{
+ int result;
+ u64 v1;
+
+ v1 = 0;
+ result = read_node(PS3_LPAR_ID_CURRENT,
+ make_first_field("bi", 0),
+ make_field("pu", pu_index),
+ 0, 0,
+ &v1, NULL);
+ *pu_id = v1;
+ return result;
+}
+
#if defined(DEBUG)
int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo)
--
^ permalink raw reply
* [patch 2/3] PS3: Add logical performance monitor device support
From: Geoff Levand @ 2008-01-05 3:12 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20080105003019.595703814@am.sony.com>
Add PS3 logical performance monitor (lpm) device support to the
PS3 system-bus and platform device registration routines.
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
arch/powerpc/platforms/ps3/device-init.c | 95 ++++++++++++++++++++++++++++++-
arch/powerpc/platforms/ps3/system-bus.c | 5 +
include/asm-powerpc/ps3.h | 7 ++
3 files changed, 106 insertions(+), 1 deletion(-)
create mode 100644 arch/powerpc/platforms/ps3/lpm.c
--- a/arch/powerpc/platforms/ps3/device-init.c
+++ b/arch/powerpc/platforms/ps3/device-init.c
@@ -30,6 +30,97 @@
#include "platform.h"
+static int __init ps3_register_lpm_devices(void)
+{
+ int result;
+ unsigned int pu_count;
+ u64 tmp1;
+ u64 tmp2;
+ struct layout {
+ struct ps3_system_bus_device dev;
+ } *p;
+
+ pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ p->dev.match_id = PS3_MATCH_ID_LPM;
+ p->dev.dev_type = PS3_DEVICE_TYPE_LPM;
+
+ result = ps3_repository_read_num_pu(&pu_count);
+
+ if (result) {
+ pr_debug("%s:%d: ps3_repository_read_num_pu failed \n",
+ __func__, __LINE__);
+ goto fail_read_repo;
+ }
+
+ /* The current lpm driver only supports a single BE processor. */
+
+ if (pu_count > 1) {
+ pr_info("%s:%d: found %u BE processors, only one supported\n",
+ __func__, __LINE__, pu_count);
+ }
+
+ result = ps3_repository_read_pu_id(0, &p->dev.lpm.pu_id);
+
+ if (result) {
+ pr_debug("%s:%d: ps3_repository_read_pu_id failed \n",
+ __func__, __LINE__);
+ goto fail_read_repo;
+ }
+
+ result = ps3_repository_read_lpm_privileges(0, &tmp1,
+ &p->dev.lpm.rights);
+
+ if (result) {
+ pr_debug("%s:%d: ps3_repository_read_lpm_privleges failed \n",
+ __func__, __LINE__);
+ goto fail_read_repo;
+ }
+
+ lv1_get_logical_partition_id(&tmp2);
+
+ if (tmp1 != tmp2) {
+ pr_debug("%s:%d: wrong lpar\n",
+ __func__, __LINE__);
+ result = -1;
+ goto fail_rights;
+ }
+
+ if (!(p->dev.lpm.rights & PS3_LPM_RIGHTS_USE_LPM)) {
+ pr_debug("%s:%d: don't have rights to use lpm\n",
+ __func__, __LINE__);
+ result = -1;
+ goto fail_rights;
+ }
+
+ pr_debug("%s:%d: pu_id %lu, rights %lu(%lxh)\n",
+ __func__, __LINE__, p->dev.lpm.pu_id, p->dev.lpm.rights,
+ p->dev.lpm.rights);
+
+ result = ps3_system_bus_device_register(&p->dev);
+
+ if (result) {
+ pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+ __func__, __LINE__);
+ goto fail_register;
+ }
+
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
+ return 0;
+
+
+fail_register:
+fail_rights:
+fail_read_repo:
+ kfree(p);
+ pr_debug(" <- %s:%d: failed\n", __func__, __LINE__);
+ return result;
+}
+
/**
* ps3_setup_gelic_device - Setup and register a gelic device instance.
*
@@ -787,6 +878,8 @@ static int __init ps3_register_devices(v
ps3_register_sound_devices();
+ ps3_register_lpm_devices();
+
pr_debug(" <- %s:%d\n", __func__, __LINE__);
return 0;
}
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -715,6 +715,7 @@ int ps3_system_bus_device_register(struc
static unsigned int dev_ioc0_count;
static unsigned int dev_sb_count;
static unsigned int dev_vuart_count;
+ static unsigned int dev_lpm_count;
if (!dev->core.parent)
dev->core.parent = &ps3_system_bus;
@@ -737,6 +738,10 @@ int ps3_system_bus_device_register(struc
snprintf(dev->core.bus_id, sizeof(dev->core.bus_id),
"vuart_%02x", ++dev_vuart_count);
break;
+ case PS3_DEVICE_TYPE_LPM:
+ snprintf(dev->core.bus_id, sizeof(dev->core.bus_id),
+ "lpm_%02x", ++dev_lpm_count);
+ break;
default:
BUG();
};
--- a/include/asm-powerpc/ps3.h
+++ b/include/asm-powerpc/ps3.h
@@ -317,6 +317,7 @@ enum ps3_match_id {
PS3_MATCH_ID_STOR_FLASH = 8,
PS3_MATCH_ID_SOUND = 9,
PS3_MATCH_ID_GRAPHICS = 10,
+ PS3_MATCH_ID_LPM = 11,
};
#define PS3_MODULE_ALIAS_EHCI "ps3:1"
@@ -329,11 +330,13 @@ enum ps3_match_id {
#define PS3_MODULE_ALIAS_STOR_FLASH "ps3:8"
#define PS3_MODULE_ALIAS_SOUND "ps3:9"
#define PS3_MODULE_ALIAS_GRAPHICS "ps3:10"
+#define PS3_MODULE_ALIAS_LPM "ps3:11"
enum ps3_system_bus_device_type {
PS3_DEVICE_TYPE_IOC0 = 1,
PS3_DEVICE_TYPE_SB,
PS3_DEVICE_TYPE_VUART,
+ PS3_DEVICE_TYPE_LPM,
};
/**
@@ -350,6 +353,10 @@ struct ps3_system_bus_device {
struct ps3_dma_region *d_region; /* SB, IOC0 */
struct ps3_mmio_region *m_region; /* SB, IOC0*/
unsigned int port_number; /* VUART */
+ struct { /* LPM */
+ u64 pu_id;
+ u64 rights;
+ } lpm;
/* struct iommu_table *iommu_table; -- waiting for BenH's cleanups */
struct device core;
--
^ permalink raw reply
* Re: [PATCH] ASoC drivers for the Freescale MPC8610 SoC
From: Grant Likely @ 2008-01-05 3:28 UTC (permalink / raw)
To: Timur Tabi; +Cc: Scott Wood, linuxppc-dev, alsa-devel
In-Reply-To: <477EED00.8070207@freescale.com>
On 1/4/08, Timur Tabi <timur@freescale.com> wrote:
> Grant Likely wrote:
> > Don't put
> > that burden on the dts author.
>
> As the DTS author in question, I hereby declare that such a requirement is not
> a burden in the slightest. Thank you.
Dude, you work for *Freescale*. The set of dts authors affected
include every engineer writing a device tree for a board that uses
this part. :-)
Cheers,
g.
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195
^ permalink raw reply
* [patch 3/3] PS3: Add logical performance monitor driver support
From: Geoff Levand @ 2008-01-05 3:30 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev, Takashi Yamamoto
In-Reply-To: <20080105003019.595703814@am.sony.com>
From: Takashi Yamamoto <Takashi02_Yamamoto@hq.scei.sony.co.jp>
Add PS3 logical performance monitor (lpm) device driver.
The PS3's LV1 hypervisor provides a Logical Performance Monitor that
abstarcts the Cell processor's performance monitor features for use
by guest operating systems.
Signed-off-by: Takashi Yamamoto <Takashi02_Yamamoto@hq.scei.sony.co.jp>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
arch/powerpc/platforms/ps3/Kconfig | 14
drivers/ps3/Makefile | 1
drivers/ps3/ps3-lpm.c | 1171 +++++++++++++++++++++++++++++++++++++
include/asm-powerpc/ps3.h | 37 +
4 files changed, 1223 insertions(+)
create mode 100644 arch/powerpc/platforms/ps3/ps3-lpm.c
--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -138,4 +138,18 @@ config PS3_FLASH
be disabled on the kernel command line using "ps3flash=off", to
not allocate this fixed buffer.
+config PS3_LPM
+ tristate "PS3 Logical Performance Monitor support"
+ depends on PPC_PS3
+ default n
+ help
+ Include support for the PS3 Logical Performance Monitor.
+
+ This support is required to use the logical performance monitor
+ of the PS3's LV1 hypervisor.
+
+ If you intend to use the advanced performance monitoring and
+ profiling support of the Cell processor with programs like
+ oprofile and perfmon, then say Y or M, otherwise say N.
+
endmenu
--- a/drivers/ps3/Makefile
+++ b/drivers/ps3/Makefile
@@ -4,3 +4,4 @@ ps3av_mod-objs += ps3av.o ps3av_cmd.o
obj-$(CONFIG_PPC_PS3) += sys-manager-core.o
obj-$(CONFIG_PS3_SYS_MANAGER) += ps3-sys-manager.o
obj-$(CONFIG_PS3_STORAGE) += ps3stor_lib.o
+obj-$(CONFIG_PS3_LPM) += ps3-lpm.o
--- /dev/null
+++ b/drivers/ps3/ps3-lpm.c
@@ -0,0 +1,1171 @@
+/*
+ * PS3 Logical Performance Monitor.
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2007 Sony Corp.
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/uaccess.h>
+#include <asm/ps3.h>
+#include <asm/lv1call.h>
+#include <asm/cell-pmu.h>
+
+#define PS3_SIZE_OF_PM_INTERNAL_TRACE_BUFFER 0x4000
+#define PS3_SIZE_OF_PM_DEFAULT_TRACE_BUFFER_CACHE 0x4000
+
+/**
+ * struct ps3_lpm_priv - private lpm device data.
+ *
+ * @mutex: Open/close mutex.
+ * @rights: The lpm rigths granted by the system policy module.
+ * @pu_id: The lv1 id of the BE prosessor for this lpm instance.
+ * @lpm_id: The lv1 id of this lpm instance.
+ * @outlet_id: The outlet created by lv1 for this lpm instance.
+ * @constructed: A flag indicating the lpm driver has been opened -- can we just use (lpm_id == ???)
+ * @tb_size: The lv1 trace buffer size
+ * @tb_cache: Trace buffer cache
+ * @tb_cache_internal: A flag indicating the trace buffer cache was allocated
+ * by the driver.
+ * @tb_cache: Trace buffer cache
+ * @sizeof_traced_data: Traced data size
+ * @sbd: the struct ps3_system_bus_device attached to this driver
+ */
+
+struct ps3_lpm_priv {
+ struct mutex mutex;
+ u64 rights;
+ u64 pu_id;
+ u64 lpm_id;
+ u64 outlet_id;
+ int constructed;
+ u64 tb_size;
+ void *tb_cache;
+ u64 tb_cache_size;
+ int tb_cache_internal;
+ u64 sizeof_traced_data;
+ u64 sizeof_total_copied_data;
+ u64 shadow_pm_control;
+ u64 shadow_pm_start_stop;
+ u64 shadow_pm_interval;
+ u64 shadow_group_control;
+ u64 shadow_debug_bus_control;
+ struct ps3_system_bus_device *sbd;
+};
+
+/**
+ * lpm_priv - Static instance of the lpm data.
+ *
+ * Since the exported routines don't support the notion of a device
+ * instance we need to hold the instance in this static variable
+ * and only allow at most one instance to be created.
+ */
+
+static struct ps3_lpm_priv *lpm_priv;
+
+static struct device *sbd_core(void)
+{
+ BUG_ON(!lpm_priv || !lpm_priv->sbd);
+ return &lpm_priv->sbd->core;
+}
+
+/**
+ * use_start_stop_bookmark - Enable the PPU bookmark trace.
+ *
+ * And it enables PPU bookmark triggers ONLY if the other triggers are not set.
+ * The start/stop bookmarks are inserted at ps3_enable_pm() and ps3_disable_pm()
+ * to start/stop LPM.
+ *
+ * Used to get good quality of the performance counter.
+ */
+
+enum {use_start_stop_bookmark = 1,};
+
+/* BOOKMARK tag macros */
+#define PS3_PM_BOOKMARK_START 0x8000000000000000ULL
+#define PS3_PM_BOOKMARK_STOP 0x4000000000000000ULL
+#define PS3_PM_BOOKMARK_TAG_KERNEL 0x1000000000000000ULL
+#define PS3_PM_BOOKMARK_TAG_USER 0x3000000000000000ULL
+#define PS3_PM_BOOKMARK_TAG_MASK_HI 0xF000000000000000ULL
+#define PS3_PM_BOOKMARK_TAG_MASK_LO 0x0F00000000000000ULL
+
+/* CBE PM CONTROL register macros */
+#define PS3_PM_CONTROL_PPU_TH0_BOOKMARK 0x00001000
+#define PS3_PM_CONTROL_PPU_TH1_BOOKMARK 0x00000800
+#define PS3_PM_CONTROL_PPU_COUNT_MODE_MASK 0x000C0000
+#define PS3_PM_CONTROL_PPU_COUNT_MODE_PROBLEM 0x00080000
+#define PS3_WRITE_PM_MASK 0xFFFFFFFFFFFFFFFFULL
+
+/* CBE PM START STOP register macros */
+#define PS3_PM_START_STOP_PPU_TH0_BOOKMARK_START 0x02000000
+#define PS3_PM_START_STOP_PPU_TH1_BOOKMARK_START 0x01000000
+#define PS3_PM_START_STOP_PPU_TH0_BOOKMARK_STOP 0x00020000
+#define PS3_PM_START_STOP_PPU_TH1_BOOKMARK_STOP 0x00010000
+#define PS3_PM_START_STOP_START_MASK 0xFF000000
+#define PS3_PM_START_STOP_STOP_MASK 0x00FF0000
+
+/* CBE PM COUNTER register macres */
+#define PS3_PM_COUNTER_MASK_HI 0xFFFFFFFF00000000ULL
+#define PS3_PM_COUNTER_MASK_LO 0x00000000FFFFFFFFULL
+
+/* BASE SIGNAL GROUP NUMBER macros */
+#define PM_ISLAND2_BASE_SIGNAL_GROUP_NUMBER 0
+#define PM_ISLAND2_SIGNAL_GROUP_NUMBER1 6
+#define PM_ISLAND2_SIGNAL_GROUP_NUMBER2 7
+#define PM_ISLAND3_BASE_SIGNAL_GROUP_NUMBER 7
+#define PM_ISLAND4_BASE_SIGNAL_GROUP_NUMBER 15
+#define PM_SPU_TRIGGER_SIGNAL_GROUP_NUMBER 17
+#define PM_SPU_EVENT_SIGNAL_GROUP_NUMBER 18
+#define PM_ISLAND5_BASE_SIGNAL_GROUP_NUMBER 18
+#define PM_ISLAND6_BASE_SIGNAL_GROUP_NUMBER 24
+#define PM_ISLAND7_BASE_SIGNAL_GROUP_NUMBER 49
+#define PM_ISLAND8_BASE_SIGNAL_GROUP_NUMBER 52
+#define PM_SIG_GROUP_SPU 41
+#define PM_SIG_GROUP_SPU_TRIGGER 42
+#define PM_SIG_GROUP_SPU_EVENT 43
+#define PM_SIG_GROUP_MFC_MAX 60
+
+/* shadow register macros */
+#define PS3_SHADOW_REG_INIT_VALUE 0xFFFFFFFF00000000ULL
+
+/* bookmark spr address */
+#define BOOKMARK_SPR_ADDR 1020
+
+void ps3_set_bookmark(u64 bookmark)
+{
+ /*
+ * As per PPE book IV, to avoid bookmark lost there
+ * must not be a traced branch within 10 cycles of
+ * setting the bookmark spr.
+ */
+
+ asm volatile("or 29, 29, 29;"); /* db10cyc */
+ mtspr(BOOKMARK_SPR_ADDR, bookmark);
+ asm volatile("or 29, 29, 29;"); /* db10cyc */
+}
+EXPORT_SYMBOL_GPL(ps3_set_bookmark);
+
+void ps3_set_pm_bookmark(u64 tag, u64 incident, u64 th_id)
+{
+ u64 bookmark;
+
+ bookmark = (get_tb() & 0x00000000FFFFFFFFULL) |
+ PS3_PM_BOOKMARK_TAG_KERNEL;
+ bookmark = ((tag << 56) & PS3_PM_BOOKMARK_TAG_MASK_LO) |
+ (incident << 48) | (th_id << 32) | bookmark;
+ ps3_set_bookmark(bookmark);
+}
+EXPORT_SYMBOL_GPL(ps3_set_pm_bookmark);
+
+/**
+ * ps3_read_phys_ctr - Read physical counter registers.
+ *
+ * Each physical counter can act as one 32 bit counter or as two 16 bit
+ * counters.
+ */
+
+u32 ps3_read_phys_ctr(u32 cpu, u32 phys_ctr)
+{
+ int result;
+ u64 counter0415;
+ u64 counter2637;
+
+ if (phys_ctr >= NR_PHYS_CTRS) {
+ dev_dbg(sbd_core(), "%s:%u: phys_ctr too big: %u\n", __func__,
+ __LINE__, phys_ctr);
+ return 0;
+ }
+
+ result = lv1_set_lpm_counter(lpm_priv->lpm_id, 0, 0, 0, 0, &counter0415,
+ &counter2637);
+ if (result) {
+ dev_err(sbd_core(), "%s:%u: lv1_set_lpm_counter failed: "
+ "phys_ctr %u, %s\n", __func__, __LINE__, phys_ctr,
+ ps3_result(result));
+ return 0;
+ }
+
+ switch (phys_ctr) {
+ case 0:
+ return counter0415 >> 32;
+ case 1:
+ return counter0415 & PS3_PM_COUNTER_MASK_LO;
+ case 2:
+ return counter2637 >> 32;
+ case 3:
+ return counter2637 & PS3_PM_COUNTER_MASK_LO;
+ default:
+ BUG();
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ps3_read_phys_ctr);
+
+/**
+ * ps3_write_phys_ctr - Write physical counter registers.
+ *
+ * Each physical counter can act as one 32 bit counter or as two 16 bit
+ * counters.
+ */
+
+void ps3_write_phys_ctr(u32 cpu, u32 phys_ctr, u32 val)
+{
+ u64 counter0415;
+ u64 counter0415_mask;
+ u64 counter2637;
+ u64 counter2637_mask;
+ int result;
+
+ if (phys_ctr >= NR_PHYS_CTRS) {
+ dev_dbg(sbd_core(), "%s:%u: phys_ctr too big: %u\n", __func__,
+ __LINE__, phys_ctr);
+ return;
+ }
+
+ switch (phys_ctr) {
+ case 0:
+ counter0415 = (u64)val << 32;
+ counter0415_mask = PS3_PM_COUNTER_MASK_HI;
+ counter2637 = 0x0;
+ counter2637_mask = 0x0;
+ break;
+ case 1:
+ counter0415 = (u64)val;
+ counter0415_mask = PS3_PM_COUNTER_MASK_LO;
+ counter2637 = 0x0;
+ counter2637_mask = 0x0;
+ break;
+ case 2:
+ counter0415 = 0x0;
+ counter0415_mask = 0x0;
+ counter2637 = (u64)val << 32;
+ counter2637_mask = PS3_PM_COUNTER_MASK_HI;
+ break;
+ case 3:
+ counter0415 = 0x0;
+ counter0415_mask = 0x0;
+ counter2637 = (u64)val;
+ counter2637_mask = PS3_PM_COUNTER_MASK_LO;
+ break;
+ default:
+ BUG();
+ }
+
+ result = lv1_set_lpm_counter(lpm_priv->lpm_id,
+ counter0415, counter0415_mask,
+ counter2637, counter2637_mask,
+ &counter0415, &counter2637);
+ if (result)
+ dev_err(sbd_core(), "%s:%u: lv1_set_lpm_counter failed: "
+ "phys_ctr %u, val %u, %s\n", __func__, __LINE__,
+ phys_ctr, val, ps3_result(result));
+}
+EXPORT_SYMBOL_GPL(ps3_write_phys_ctr);
+
+/**
+ * ps3_read_ctr - Read counter.
+ *
+ * Read 16 or 32 bits depending on the current size of the counter.
+ * Counters 4, 5, 6 & 7 are always 16 bit.
+ */
+
+u32 ps3_read_ctr(u32 cpu, u32 ctr)
+{
+ u32 val;
+ u32 phys_ctr = ctr & (NR_PHYS_CTRS - 1);
+
+ val = ps3_read_phys_ctr(cpu, phys_ctr);
+
+ if (ps3_get_ctr_size(cpu, phys_ctr) == 16)
+ val = (ctr < NR_PHYS_CTRS) ? (val >> 16) : (val & 0xffff);
+
+ return val;
+}
+EXPORT_SYMBOL_GPL(ps3_read_ctr);
+
+/**
+ * ps3_write_ctr - Write counter.
+ *
+ * Write 16 or 32 bits depending on the current size of the counter.
+ * Counters 4, 5, 6 & 7 are always 16 bit.
+ */
+
+void ps3_write_ctr(u32 cpu, u32 ctr, u32 val)
+{
+ u32 phys_ctr;
+ u32 phys_val;
+
+ phys_ctr = ctr & (NR_PHYS_CTRS - 1);
+
+ if (ps3_get_ctr_size(cpu, phys_ctr) == 16) {
+ phys_val = ps3_read_phys_ctr(cpu, phys_ctr);
+
+ if (ctr < NR_PHYS_CTRS)
+ val = (val << 16) | (phys_val & 0xffff);
+ else
+ val = (val & 0xffff) | (phys_val & 0xffff0000);
+ }
+
+ ps3_write_phys_ctr(cpu, phys_ctr, val);
+}
+EXPORT_SYMBOL_GPL(ps3_write_ctr);
+
+/**
+ * ps3_read_pm07_control - Read counter control registers.
+ *
+ * Each logical counter has a corresponding control register.
+ */
+
+u32 ps3_read_pm07_control(u32 cpu, u32 ctr)
+{
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ps3_read_pm07_control);
+
+/**
+ * ps3_write_pm07_control - Write counter control registers.
+ *
+ * Each logical counter has a corresponding control register.
+ */
+
+void ps3_write_pm07_control(u32 cpu, u32 ctr, u32 val)
+{
+ int result;
+ static const u64 mask = 0xFFFFFFFFFFFFFFFFULL;
+ u64 old_value;
+
+ if (ctr >= NR_CTRS) {
+ dev_dbg(sbd_core(), "%s:%u: ctr too big: %u\n", __func__,
+ __LINE__, ctr);
+ return;
+ }
+
+ result = lv1_set_lpm_counter_control(lpm_priv->lpm_id, ctr, val, mask,
+ &old_value);
+ if (result)
+ dev_err(sbd_core(), "%s:%u: lv1_set_lpm_counter_control "
+ "failed: ctr %u, %s\n", __func__, __LINE__, ctr,
+ ps3_result(result));
+}
+EXPORT_SYMBOL_GPL(ps3_write_pm07_control);
+
+/**
+ * ps3_read_pm - Read Other LPM control registers.
+ */
+
+u32 ps3_read_pm(u32 cpu, enum pm_reg_name reg)
+{
+ switch (reg) {
+ case pm_control:
+ return lpm_priv->shadow_pm_control;
+ case trace_address:
+ return CBE_PM_TRACE_BUF_EMPTY;
+ case pm_start_stop:
+ return lpm_priv->shadow_pm_start_stop;
+ default:
+ dev_dbg(sbd_core(), "%s:%u: unknown reg: %d\n", __func__,
+ __LINE__, reg);
+ BUG();
+ break;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ps3_read_pm);
+
+/**
+ * ps3_write_pm - Write Other LPM control registers.
+ */
+
+void ps3_write_pm(u32 cpu, enum pm_reg_name reg, u32 val)
+{
+ int result = 0;
+ u64 dummy;
+
+ switch (reg) {
+ case group_control:
+ if (val != lpm_priv->shadow_group_control)
+ result = lv1_set_lpm_group_control(lpm_priv->lpm_id,
+ val,
+ PS3_WRITE_PM_MASK,
+ &dummy);
+ lpm_priv->shadow_group_control = val;
+ break;
+ case debug_bus_control:
+ if (val != lpm_priv->shadow_debug_bus_control)
+ result = lv1_set_lpm_debug_bus_control(lpm_priv->lpm_id,
+ val,
+ PS3_WRITE_PM_MASK,
+ &dummy);
+ lpm_priv->shadow_debug_bus_control = val;
+ break;
+ case pm_control:
+ if (use_start_stop_bookmark)
+ val |= (PS3_PM_CONTROL_PPU_TH0_BOOKMARK |
+ PS3_PM_CONTROL_PPU_TH1_BOOKMARK);
+ if (val != lpm_priv->shadow_pm_control)
+ result = lv1_set_lpm_general_control(lpm_priv->lpm_id,
+ val,
+ PS3_WRITE_PM_MASK,
+ 0, 0, &dummy,
+ &dummy);
+ lpm_priv->shadow_pm_control = val;
+ break;
+ case pm_interval:
+ if (val != lpm_priv->shadow_pm_interval)
+ result = lv1_set_lpm_interval(lpm_priv->lpm_id, val,
+ PS3_WRITE_PM_MASK, &dummy);
+ lpm_priv->shadow_pm_interval = val;
+ break;
+ case pm_start_stop:
+ if (val != lpm_priv->shadow_pm_start_stop)
+ result = lv1_set_lpm_trigger_control(lpm_priv->lpm_id,
+ val,
+ PS3_WRITE_PM_MASK,
+ &dummy);
+ lpm_priv->shadow_pm_start_stop = val;
+ break;
+ default:
+ dev_dbg(sbd_core(), "%s:%u: unknown reg: %d\n", __func__,
+ __LINE__, reg);
+ BUG();
+ break;
+ }
+
+ if (result)
+ dev_err(sbd_core(), "%s:%u: lv1 set_control failed: "
+ "reg %u, %s\n", __func__, __LINE__, reg,
+ ps3_result(result));
+}
+EXPORT_SYMBOL_GPL(ps3_write_pm);
+
+/**
+ * ps3_get_ctr_size - Get the size of a physical counter.
+ *
+ * Returns either 16 or 32.
+ */
+
+u32 ps3_get_ctr_size(u32 cpu, u32 phys_ctr)
+{
+ u32 pm_ctrl;
+
+ if (phys_ctr >= NR_PHYS_CTRS) {
+ dev_dbg(sbd_core(), "%s:%u: phys_ctr too big: %u\n", __func__,
+ __LINE__, phys_ctr);
+ return 0;
+ }
+
+ pm_ctrl = ps3_read_pm(cpu, pm_control);
+ return (pm_ctrl & CBE_PM_16BIT_CTR(phys_ctr)) ? 16 : 32;
+}
+EXPORT_SYMBOL_GPL(ps3_get_ctr_size);
+
+/**
+ * ps3_set_ctr_size - Set the size of a physical counter to 16 or 32 bits.
+ */
+
+void ps3_set_ctr_size(u32 cpu, u32 phys_ctr, u32 ctr_size)
+{
+ u32 pm_ctrl;
+
+ if (phys_ctr >= NR_PHYS_CTRS) {
+ dev_dbg(sbd_core(), "%s:%u: phys_ctr too big: %u\n", __func__,
+ __LINE__, phys_ctr);
+ return;
+ }
+
+ pm_ctrl = ps3_read_pm(cpu, pm_control);
+
+ switch (ctr_size) {
+ case 16:
+ pm_ctrl |= CBE_PM_16BIT_CTR(phys_ctr);
+ ps3_write_pm(cpu, pm_control, pm_ctrl);
+ break;
+
+ case 32:
+ pm_ctrl &= ~CBE_PM_16BIT_CTR(phys_ctr);
+ ps3_write_pm(cpu, pm_control, pm_ctrl);
+ break;
+ default:
+ BUG();
+ }
+}
+EXPORT_SYMBOL_GPL(ps3_set_ctr_size);
+
+static u64 pm_translate_signal_group_number_on_island2(u64 subgroup)
+{
+
+ if (subgroup == 2)
+ subgroup = 3;
+
+ if (subgroup <= 6)
+ return PM_ISLAND2_BASE_SIGNAL_GROUP_NUMBER + subgroup;
+ else if (subgroup == 7)
+ return PM_ISLAND2_SIGNAL_GROUP_NUMBER1;
+ else
+ return PM_ISLAND2_SIGNAL_GROUP_NUMBER2;
+}
+
+static u64 pm_translate_signal_group_number_on_island3(u64 subgroup)
+{
+
+ switch (subgroup) {
+ case 2:
+ case 3:
+ case 4:
+ subgroup += 2;
+ break;
+ case 5:
+ subgroup = 8;
+ break;
+ default:
+ break;
+ }
+ return PM_ISLAND3_BASE_SIGNAL_GROUP_NUMBER + subgroup;
+}
+
+static u64 pm_translate_signal_group_number_on_island4(u64 subgroup)
+{
+ return PM_ISLAND4_BASE_SIGNAL_GROUP_NUMBER + subgroup;
+}
+
+static u64 pm_translate_signal_group_number_on_island5(u64 subgroup)
+{
+
+ switch (subgroup) {
+ case 3:
+ subgroup = 4;
+ break;
+ case 4:
+ subgroup = 6;
+ break;
+ default:
+ break;
+ }
+ return PM_ISLAND5_BASE_SIGNAL_GROUP_NUMBER + subgroup;
+}
+
+static u64 pm_translate_signal_group_number_on_island6(u64 subgroup,
+ u64 subsubgroup)
+{
+ switch (subgroup) {
+ case 3:
+ case 4:
+ case 5:
+ subgroup += 1;
+ break;
+ default:
+ break;
+ }
+
+ switch (subsubgroup) {
+ case 4:
+ case 5:
+ case 6:
+ subsubgroup += 2;
+ break;
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ subsubgroup += 4;
+ break;
+ case 11:
+ case 12:
+ case 13:
+ subsubgroup += 5;
+ break;
+ default:
+ break;
+ }
+
+ if (subgroup <= 5)
+ return (PM_ISLAND6_BASE_SIGNAL_GROUP_NUMBER + subgroup);
+ else
+ return (PM_ISLAND6_BASE_SIGNAL_GROUP_NUMBER + subgroup
+ + subsubgroup - 1);
+}
+
+static u64 pm_translate_signal_group_number_on_island7(u64 subgroup)
+{
+ return PM_ISLAND7_BASE_SIGNAL_GROUP_NUMBER + subgroup;
+}
+
+static u64 pm_translate_signal_group_number_on_island8(u64 subgroup)
+{
+ return PM_ISLAND8_BASE_SIGNAL_GROUP_NUMBER + subgroup;
+}
+
+static u64 pm_signal_group_to_ps3_lv1_signal_group(u64 group)
+{
+ u64 island;
+ u64 subgroup;
+ u64 subsubgroup;
+
+ subgroup = 0;
+ subsubgroup = 0;
+ island = 0;
+ if (group < 1000) {
+ if (group < 100) {
+ if (20 <= group && group < 30) {
+ island = 2;
+ subgroup = group - 20;
+ } else if (30 <= group && group < 40) {
+ island = 3;
+ subgroup = group - 30;
+ } else if (40 <= group && group < 50) {
+ island = 4;
+ subgroup = group - 40;
+ } else if (50 <= group && group < 60) {
+ island = 5;
+ subgroup = group - 50;
+ } else if (60 <= group && group < 70) {
+ island = 6;
+ subgroup = group - 60;
+ } else if (70 <= group && group < 80) {
+ island = 7;
+ subgroup = group - 70;
+ } else if (80 <= group && group < 90) {
+ island = 8;
+ subgroup = group - 80;
+ }
+ } else if (200 <= group && group < 300) {
+ island = 2;
+ subgroup = group - 200;
+ } else if (600 <= group && group < 700) {
+ island = 6;
+ subgroup = 5;
+ subsubgroup = group - 650;
+ }
+ } else if (6000 <= group && group < 7000) {
+ island = 6;
+ subgroup = 5;
+ subsubgroup = group - 6500;
+ }
+
+ switch (island) {
+ case 2:
+ return pm_translate_signal_group_number_on_island2(subgroup);
+ case 3:
+ return pm_translate_signal_group_number_on_island3(subgroup);
+ case 4:
+ return pm_translate_signal_group_number_on_island4(subgroup);
+ case 5:
+ return pm_translate_signal_group_number_on_island5(subgroup);
+ case 6:
+ return pm_translate_signal_group_number_on_island6(subgroup,
+ subsubgroup);
+ case 7:
+ return pm_translate_signal_group_number_on_island7(subgroup);
+ case 8:
+ return pm_translate_signal_group_number_on_island8(subgroup);
+ default:
+ dev_dbg(sbd_core(), "%s:%u: island not found: %lu\n", __func__,
+ __LINE__, group);
+ BUG();
+ break;
+ }
+ return 0;
+}
+
+static u64 pm_bus_word_to_ps3_lv1_bus_word(u8 word)
+{
+
+ switch (word) {
+ case 1:
+ return 0xF000;
+ case 2:
+ return 0x0F00;
+ case 4:
+ return 0x00F0;
+ case 8:
+ default:
+ return 0x000F;
+ }
+}
+
+static int __ps3_set_signal(u64 lv1_signal_group, u64 bus_select,
+ u64 signal_select, u64 attr1, u64 attr2, u64 attr3)
+{
+ int ret;
+
+ ret = lv1_set_lpm_signal(lpm_priv->lpm_id, lv1_signal_group, bus_select,
+ signal_select, attr1, attr2, attr3);
+ if (ret)
+ dev_err(sbd_core(),
+ "%s:%u: error:%d 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
+ __func__, __LINE__, ret, lv1_signal_group, bus_select,
+ signal_select, attr1, attr2, attr3);
+
+ return ret;
+}
+
+int ps3_set_signal(u64 signal_group, u8 signal_bit, u16 sub_unit,
+ u8 bus_word)
+{
+ int ret;
+ u64 lv1_signal_group;
+ u64 bus_select;
+ u64 signal_select;
+ u64 attr1, attr2, attr3;
+
+ if (signal_group == 0)
+ return __ps3_set_signal(0, 0, 0, 0, 0, 0);
+
+ lv1_signal_group =
+ pm_signal_group_to_ps3_lv1_signal_group(signal_group);
+ bus_select = pm_bus_word_to_ps3_lv1_bus_word(bus_word);
+
+ switch (signal_group) {
+ case PM_SIG_GROUP_SPU_TRIGGER:
+ signal_select = 1;
+ signal_select = signal_select << (63 - signal_bit);
+ break;
+ case PM_SIG_GROUP_SPU_EVENT:
+ signal_select = 1;
+ signal_select = (signal_select << (63 - signal_bit)) | 0x3;
+ break;
+ default:
+ signal_select = 0;
+ break;
+ }
+
+ /*
+ * 0: physical object.
+ * 1: logical object.
+ * This parameter is only used for the PPE and SPE signals.
+ */
+ attr1 = 1;
+
+ /*
+ * This parameter is used to specify the target physical/logical
+ * PPE/SPE object.
+ */
+ if (PM_SIG_GROUP_SPU <= signal_group &&
+ signal_group < PM_SIG_GROUP_MFC_MAX)
+ attr2 = sub_unit;
+ else
+ attr2 = lpm_priv->pu_id;;
+
+ /*
+ * This parameter is only used for setting the SPE signal.
+ */
+ attr3 = 0;
+
+ ret = __ps3_set_signal(lv1_signal_group, bus_select, signal_select,
+ attr1, attr2, attr3);
+ if (ret)
+ dev_err(sbd_core(), "%s:%u: __ps3_set_signal failed: %d\n",
+ __func__, __LINE__, ret);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(ps3_set_signal);
+
+inline u32 ps3_get_hw_thread_id(int cpu)
+{
+ return cpu;
+}
+EXPORT_SYMBOL_GPL(ps3_get_hw_thread_id);
+
+/**
+ * ps3_enable_pm - Enable the entire performance monitoring unit.
+ *
+ * When we enable the LPM, all pending writes to counters get committed.
+ */
+
+void ps3_enable_pm(u32 cpu)
+{
+ int result;
+ u64 tmp;
+ int insert_bookmark = 0;
+
+ if (use_start_stop_bookmark) {
+ if (!(lpm_priv->shadow_pm_start_stop &
+ (PS3_PM_START_STOP_START_MASK
+ | PS3_PM_START_STOP_STOP_MASK))) {
+ result = lv1_set_lpm_trigger_control(lpm_priv->lpm_id,
+ (PS3_PM_START_STOP_PPU_TH0_BOOKMARK_START |
+ PS3_PM_START_STOP_PPU_TH1_BOOKMARK_START |
+ PS3_PM_START_STOP_PPU_TH0_BOOKMARK_STOP |
+ PS3_PM_START_STOP_PPU_TH1_BOOKMARK_STOP),
+ 0xFFFFFFFFFFFFFFFFULL, &tmp);
+
+ if (result)
+ dev_err(sbd_core(), "%s:%u: "
+ "lv1_set_lpm_trigger_control failed: "
+ "%s\n", __func__, __LINE__,
+ ps3_result(result));
+
+ insert_bookmark = !result;
+ }
+ }
+
+ result = lv1_start_lpm(lpm_priv->lpm_id);
+
+ if (result)
+ dev_err(sbd_core(), "%s:%u: lv1_start_lpm failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
+
+ if (use_start_stop_bookmark && result && insert_bookmark)
+ ps3_set_bookmark(get_tb() | PS3_PM_BOOKMARK_START);
+}
+EXPORT_SYMBOL_GPL(ps3_enable_pm);
+
+/**
+ * ps3_disable_pm - Disable the entire performance monitoring unit.
+ */
+
+void ps3_disable_pm(u32 cpu)
+{
+ int result;
+ u64 param = 0;
+
+ ps3_set_bookmark(get_tb() | PS3_PM_BOOKMARK_STOP);
+
+ result = lv1_stop_lpm(lpm_priv->lpm_id, ¶m);
+
+ if (result) {
+ dev_err(sbd_core(), "%s:%u: lv1_stop_lpm failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
+ return;
+ }
+
+ lpm_priv->sizeof_traced_data = param;
+ lpm_priv->sizeof_total_copied_data = 0;
+}
+EXPORT_SYMBOL_GPL(ps3_disable_pm);
+
+/**
+ * _ps3_copy_trace_buffer - Copy the trace buffer.
+ */
+
+static u64 _ps3_copy_trace_buffer(u64 offset, u64 size, u64 *to, int to_user)
+{
+ int result;
+ u64 sizeof_copied_data;
+
+ if (offset >= lpm_priv->sizeof_traced_data)
+ return 0;
+
+ result = lv1_copy_lpm_trace_buffer(lpm_priv->lpm_id, offset, size,
+ &sizeof_copied_data);
+ if (result) {
+ dev_err(sbd_core(), "%s:%u: lv1_copy_lpm_trace_buffer failed: "
+ "offset 0x%lx, size 0x%lx: %s\n", __func__, __LINE__,
+ offset, size, ps3_result(result));
+ return 0;
+ }
+
+ if (to_user) {
+ result = copy_to_user((void __user *)to, lpm_priv->tb_cache,
+ sizeof_copied_data);
+ if (result) {
+ dev_err(sbd_core(), "%s:%u: copy_to_user() error. "
+ "offset:0x%lx size:0x%lx dest:0x%p src:0x%p\n",
+ __func__, __LINE__, offset, sizeof_copied_data,
+ to, lpm_priv->tb_cache);
+ return 0;
+ }
+ } else
+ memcpy(to, lpm_priv->tb_cache, sizeof_copied_data);
+
+ return sizeof_copied_data;
+}
+
+u64 ps3_copy_trace_buffer(u64 offset, u64 size, void *to, int to_user)
+{
+ u64 sz;
+ u64 cp_size;
+ u64 total_cp_size;
+
+ if (!lpm_priv->tb_cache)
+ return 0;
+
+ cp_size = size;
+ if (cp_size > lpm_priv->tb_cache_size)
+ cp_size = lpm_priv->tb_cache_size;
+
+ total_cp_size = 0;
+ while (total_cp_size < size) {
+ sz = _ps3_copy_trace_buffer(offset, cp_size, to, to_user);
+ if (!sz)
+ break;
+
+ total_cp_size += sz;
+ offset += sz;
+ to = ((u8 *)to + sz);
+ }
+ return total_cp_size;
+}
+
+/**
+ * ps3_get_and_clear_pm_interrupts -
+ *
+ * Clearing interrupts for the entire performance monitoring unit.
+ * Reading pm_status clears the interrupt bits.
+ */
+
+u32 ps3_get_and_clear_pm_interrupts(u32 cpu)
+{
+ return ps3_read_pm(cpu, pm_status);
+}
+EXPORT_SYMBOL_GPL(ps3_get_and_clear_pm_interrupts);
+
+/**
+ * ps3_enable_pm_interrupts -
+ *
+ * Enabling interrupts for the entire performance monitoring unit.
+ * Enables the interrupt bits in the pm_status register.
+ */
+
+void ps3_enable_pm_interrupts(u32 cpu, u32 thread, u32 mask)
+{
+ if (mask)
+ ps3_write_pm(cpu, pm_status, mask);
+}
+EXPORT_SYMBOL_GPL(ps3_enable_pm_interrupts);
+
+/**
+ * ps3_enable_pm_interrupts -
+ *
+ * Disabling interrupts for the entire performance monitoring unit.
+ */
+
+void ps3_disable_pm_interrupts(u32 cpu)
+{
+ ps3_get_and_clear_pm_interrupts(cpu);
+ ps3_write_pm(cpu, pm_status, 0);
+}
+EXPORT_SYMBOL_GPL(ps3_disable_pm_interrupts);
+
+/**
+ * ps3_lpm_open - Open the lpm device.
+ * @tb_cache: Optional user supplied buffer for the tb cache. If NULL,
+ * the driver will use an internally managed tb cache buffer.
+ * @tb_cache_size: The size in bytes of the user supplied tb cache buffer.
+ * Unused if @tb_cache is NULL.
+ * @tb_type:
+ *
+ */
+
+int ps3_lpm_open(void *tb_cache, u64 tb_cache_size, u64 tb_type)
+{
+ int result;
+ u64 cbe_node_id;
+ u64 tb_size;
+ u64 ctrl_opt;
+ u64 tb_cache_lpar_addr;
+ u64 lpm_id;
+ u64 outlet_id;
+ u64 used_tb_size;
+
+ if (!lpm_priv) {
+ BUG();
+ return -ENODEV;
+ }
+
+ mutex_lock(&lpm_priv->mutex);
+
+ if (lpm_priv->constructed) {
+ dev_err(sbd_core(), "%s:%u: called twice.\n", __func__,
+ __LINE__);
+ result = -EBUSY;
+ goto unlock;
+ }
+
+ if (tb_cache)
+ lpm_priv->tb_cache_internal = 0;
+ else {
+ dev_dbg(sbd_core(), "%s:%u: Using internal TB cache\n",
+ __func__, __LINE__);
+
+ lpm_priv->tb_cache_internal = 1;
+ tb_cache_size = PS3_SIZE_OF_PM_DEFAULT_TRACE_BUFFER_CACHE;
+ tb_cache = kzalloc(tb_cache_size, GFP_KERNEL);
+
+ if (!tb_cache) {
+ dev_err(sbd_core(), "%s:%u: alloc internal tb_cache "
+ "failed\n", __func__, __LINE__);
+ result = -ENOMEM;
+ goto fail_malloc;
+ }
+ }
+
+ cbe_node_id = 0;
+ if (tb_cache) {
+ if (tb_type == 0) {
+ /* no trace buffer */
+ tb_type = 0;
+ tb_size = 0;
+ ctrl_opt = 0;
+ tb_cache_lpar_addr = 0;
+ } else if (tb_type == 1) {
+ /* internal trace buffer */
+ tb_size = PS3_SIZE_OF_PM_INTERNAL_TRACE_BUFFER;
+ ctrl_opt = 0;
+ } else {
+ dev_err(sbd_core(), "%s:%u: Unkown TB type: 0x%lx\n",
+ __func__, __LINE__, tb_type);
+ result = -EINVAL;
+ goto fail_type;
+ }
+ tb_cache_lpar_addr = (u64)ps3_mm_phys_to_lpar(__pa(tb_cache));
+ } else {
+ /* no trace buffer */
+ tb_type = 0;
+ tb_size = 0;
+ ctrl_opt = 0;
+ tb_cache_lpar_addr = 0;
+ }
+
+ result = lv1_construct_lpm(cbe_node_id, tb_type, tb_size, ctrl_opt,
+ tb_cache_lpar_addr, tb_cache_size,
+ &lpm_id, &outlet_id, &used_tb_size);
+
+ if (result) {
+ dev_err(sbd_core(), "%s:%u: lv1_construct_lpm failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
+ result = -EINVAL;
+ goto fail_construct;
+ }
+
+ lpm_priv->constructed = 1;
+ lpm_priv->tb_cache = tb_cache;
+ lpm_priv->tb_cache_size = tb_cache_size;
+ lpm_priv->lpm_id = lpm_id;
+ lpm_priv->outlet_id = outlet_id;
+ lpm_priv->tb_size = used_tb_size;
+ lpm_priv->shadow_pm_control = PS3_SHADOW_REG_INIT_VALUE;
+ lpm_priv->shadow_pm_start_stop = PS3_SHADOW_REG_INIT_VALUE;
+ lpm_priv->shadow_pm_interval = PS3_SHADOW_REG_INIT_VALUE;
+ lpm_priv->shadow_group_control = PS3_SHADOW_REG_INIT_VALUE;
+ lpm_priv->shadow_debug_bus_control = PS3_SHADOW_REG_INIT_VALUE;
+
+ dev_dbg(sbd_core(), "%s:%u: lpm id 0x%lx, outlet 0x%lx, "
+ "tb_size 0x%lx\n", __func__, __LINE__, lpm_priv->lpm_id,
+ lpm_priv->outlet_id, lpm_priv->tb_size);
+
+ mutex_unlock(&lpm_priv->mutex);
+ return 0;
+
+fail_construct:
+fail_type:
+ if (lpm_priv->tb_cache_internal) {
+ kfree(lpm_priv->tb_cache);
+ lpm_priv->tb_cache = NULL;
+ }
+fail_malloc:
+unlock:
+ mutex_unlock(&lpm_priv->mutex);
+ return result;
+}
+EXPORT_SYMBOL_GPL(ps3_lpm_open);
+
+/**
+ * ps3_lpm_close - Close the lpm device.
+ *
+ */
+
+int ps3_lpm_close(void)
+{
+ dev_dbg(sbd_core(), "%s:%u\n", __func__, __LINE__);
+
+ mutex_lock(&lpm_priv->mutex);
+
+ if (lpm_priv->constructed)
+ lv1_destruct_lpm(lpm_priv->lpm_id);
+
+ lpm_priv->constructed = 0;
+ lpm_priv->lpm_id = 0;
+
+ if (lpm_priv->tb_cache_internal) {
+ kfree(lpm_priv->tb_cache);
+ lpm_priv->tb_cache = NULL;
+ }
+
+ mutex_unlock(&lpm_priv->mutex);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ps3_lpm_close);
+
+static int __devinit ps3_lpm_probe(struct ps3_system_bus_device *dev)
+{
+ dev_dbg(&dev->core, " -> %s:%u\n", __func__, __LINE__);
+
+ if (lpm_priv) {
+ dev_info(&dev->core, "%s:%u: called twice\n",
+ __func__, __LINE__);
+ return -EBUSY;
+ }
+
+ lpm_priv = kzalloc(sizeof(*lpm_priv), GFP_KERNEL);
+
+ if (!lpm_priv)
+ return -ENOMEM;
+
+ lpm_priv->sbd = dev;
+ lpm_priv->pu_id = dev->lpm.pu_id;
+ lpm_priv->rights = dev->lpm.rights;
+ mutex_init(&lpm_priv->mutex);
+
+ dev_info(&dev->core, " <- %s:%u:\n", __func__, __LINE__);
+
+ return 0;
+}
+
+static int ps3_lpm_remove(struct ps3_system_bus_device *dev)
+{
+ dev_dbg(&dev->core, " -> %s:%u:\n", __func__, __LINE__);
+
+ ps3_lpm_close();
+
+ kfree(lpm_priv);
+ lpm_priv = NULL;
+
+ dev_info(&dev->core, " <- %s:%u:\n", __func__, __LINE__);
+ return 0;
+}
+
+static struct ps3_system_bus_driver ps3_lpm_driver = {
+ .match_id = PS3_MATCH_ID_LPM,
+ .core.name = "ps3-lpm",
+ .core.owner = THIS_MODULE,
+ .probe = ps3_lpm_probe,
+ .remove = ps3_lpm_remove,
+ .shutdown = ps3_lpm_remove,
+};
+
+static int __init ps3_lpm_init(void)
+{
+ pr_debug("%s:%d:\n", __func__, __LINE__);
+ return ps3_system_bus_driver_register(&ps3_lpm_driver);
+}
+
+static void __exit ps3_lpm_exit(void)
+{
+ pr_debug("%s:%d:\n", __func__, __LINE__);
+ ps3_system_bus_driver_unregister(&ps3_lpm_driver);
+}
+
+module_init(ps3_lpm_init);
+module_exit(ps3_lpm_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("PS3 Logical Performance Monitor Driver");
+MODULE_AUTHOR("Sony Corporation");
+MODULE_ALIAS(PS3_MODULE_ALIAS_LPM);
--- a/include/asm-powerpc/ps3.h
+++ b/include/asm-powerpc/ps3.h
@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/device.h>
+#include "cell-pmu.h"
union ps3_firmware_version {
u64 raw;
@@ -445,5 +446,41 @@ struct ps3_prealloc {
extern struct ps3_prealloc ps3fb_videomemory;
extern struct ps3_prealloc ps3flash_bounce_buffer;
+/* logical performance monitor */
+
+enum ps3_lpm_rights {
+ PS3_LPM_RIGHTS_USE_LPM = 1,
+};
+
+int ps3_lpm_open(void *tb_cache, u64 tb_cache_size, u64 tb_type);
+int ps3_lpm_close(void);
+void ps3_set_bookmark(u64 bookmark);
+void ps3_set_pm_bookmark(u64 tag, u64 incident, u64 th_id);
+u64 ps3_copy_trace_buffer(u64 offset, u64 size, void *to, int to_user);
+int ps3_set_signal(u64 rtas_signal_group, u8 signal_bit, u16 sub_unit,
+ u8 bus_word);
+
+u32 ps3_read_phys_ctr(u32 cpu, u32 phys_ctr);
+void ps3_write_phys_ctr(u32 cpu, u32 phys_ctr, u32 val);
+u32 ps3_read_ctr(u32 cpu, u32 ctr);
+void ps3_write_ctr(u32 cpu, u32 ctr, u32 val);
+
+u32 ps3_read_pm07_control(u32 cpu, u32 ctr);
+void ps3_write_pm07_control(u32 cpu, u32 ctr, u32 val);
+u32 ps3_read_pm(u32 cpu, enum pm_reg_name reg);
+void ps3_write_pm(u32 cpu, enum pm_reg_name reg, u32 val);
+
+u32 ps3_get_ctr_size(u32 cpu, u32 phys_ctr);
+void ps3_set_ctr_size(u32 cpu, u32 phys_ctr, u32 ctr_size);
+
+void ps3_enable_pm(u32 cpu);
+void ps3_disable_pm(u32 cpu);
+void ps3_enable_pm_interrupts(u32 cpu, u32 thread, u32 mask);
+void ps3_disable_pm_interrupts(u32 cpu);
+
+u32 ps3_get_and_clear_pm_interrupts(u32 cpu);
+void ps3_sync_irq(int node);
+u32 ps3_get_hw_thread_id(int cpu);
+u64 ps3_get_spe_id(void *arg);
#endif
--
^ permalink raw reply
* porting linux 2.6 to ml410, no output after "Now booting the kernel", and some other questions
From: diak sim @ 2008-01-05 3:53 UTC (permalink / raw)
To: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 878 bytes --]
my kernel is linux-2.6-vertex 2.6.23-rc2.
i make sure that the kernel is running, but nothing output to the serial terminal after "Now booting the kernel".
before load_kernel() return, i can use puts() to do some display.
i've selected 16550 serial port and add console=ttyS0 to the cmdline.
another question,
after load_kernel() function, where is the next step? is it head.S?
if i am in main.c using start_kernel() function, how can i output something to the serial?
referencing many info, so mass, i don't know how to debug this. the XMD provide a gdbserver to connect,
but when i use gdb to "target remote" it, it says packet too long.....
thanks.
___________________________________________________________
雅虎邮箱传递新年祝福,个性贺卡送亲朋!
http://cn.mail.yahoo.com/gc/index.html?entry=5&souce=mail_mailletter_tagline
[-- Attachment #2: Type: text/html, Size: 1055 bytes --]
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox