* RE: [PATCH v7 3/9] add Freescale SerDes PHY support
From: Liu Dave @ 2007-11-21 3:48 UTC (permalink / raw)
To: Kumar Gala, Li Yang; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <68738B73-92D6-459F-88A7-BBE66967A3A0@kernel.crashing.org>
> On Oct 19, 2007, at 10:35 AM, Grant Likely wrote:
>=20
> > On 10/19/07, Li Yang <leoli@freescale.com> wrote:
> >> The SerDes(serializer/deserializer) PHY block is a new SoC=20
> block used
> >> in Freescale chips to support multiple serial interfaces,=20
> such as PCI
> >> Express, SGMII, SATA.
> >
> > This looks like board setup behaviour. Shouldn't setting this up be
> > the responsibility firmware? And failing that, I think it should be
> > done directly by the platform setup function (in other=20
> words; make it
> > a helper function and call it at board setup time). =20
> Besides, you want
> > to provide guarantees that the board is setup correctly before the
> > device driver that uses it gets probed.
> >
> > Cheers,
> > g.
>=20
> Upon further review of all this I don't think this belongs in the =20
> kernel at all. This is one time setup and should be done in firmware.
The latest u-boot supports the serdes initialization for 837x.
So, it can be dropped from kernel for now.
Dave
^ permalink raw reply
* Re: [PATCH] sys_indirect kernel implementation for PowerPC
From: Stephen Rothwell @ 2007-11-21 3:49 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Ulrich Drepper
In-Reply-To: <20071121144245.e8abf9e8.sfr@canb.auug.org.au>
[-- Attachment #1: Type: text/plain, Size: 302 bytes --]
On Wed, 21 Nov 2007 14:08:46 +1100 Paul Mackerras <paulus@samba.org> wrote:
>
> +struct indirect_registers32 {
In fact, you should probably call this struct compat_indirect_registers ...
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH v7 3/9] add Freescale SerDes PHY support
From: Kumar Gala @ 2007-11-21 4:01 UTC (permalink / raw)
To: Li Yang; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <989B956029373F45A0B8AF029708189001A1C7DF@zch01exm26.fsl.freescale.net>
>> Upon further review of all this I don't think this belongs in
>> the kernel at all. This is one time setup and should be done
>> in firmware.
>
> I'm ok for it to be taken care of in u-boot for now. However, if we
> later plan to add power management support to this block. We probably
> have to do it in kernel.
How does pwr mgmt come into play w/SerDes?
- k
^ permalink raw reply
* Re: [PATCH v7 3/9] add Freescale SerDes PHY support
From: Kumar Gala @ 2007-11-21 4:05 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, Li Yang, Paul Mackerras
In-Reply-To: <56B46498-9213-49A1-B667-40B286291461@kernel.crashing.org>
On Nov 20, 2007, at 10:01 PM, Kumar Gala wrote:
>>> Upon further review of all this I don't think this belongs in
>>> the kernel at all. This is one time setup and should be done
>>> in firmware.
>>
>> I'm ok for it to be taken care of in u-boot for now. However, if we
>> later plan to add power management support to this block. We
>> probably
>> have to do it in kernel.
>
> How does pwr mgmt come into play w/SerDes?
Never mind, if we do add pwr mgmt it looks like all we need to know is
what SerDes is associated with the device.
- k
^ permalink raw reply
* Re: [PATCH] sys_indirect kernel implementation for PowerPC
From: Kumar Gala @ 2007-11-21 4:45 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <18243.41278.72798.100000@cargo.ozlabs.ibm.com>
On Nov 20, 2007, at 9:08 PM, Paul Mackerras wrote:
> This implements sys_indirect for 32-bit and 64-bit powerpc machines,
> including a 32-bit compatibility implementation for 64-bit powerpc.
> I decided to use assembly language for call_syscall because on 64-bit
> powerpc the system call table has the addresses of the function text
> rather than pointers to function descriptors; hence the system call
> functions can't be called from C via the system call table.
Admit it you were bored and wanted to write some PPC asm ;)
- k
^ permalink raw reply
* [PATCH 0/3] Device tree docs updates for FSL periphs
From: Kumar Gala @ 2007-11-21 5:11 UTC (permalink / raw)
To: linuxppc-dev
All,
Please review these updates to booting-without-of.txt for the FSL periphs:
* SATA
* RapidIO
* DMA
They are intended to encompass patches posted before with some changes
that I've made.
- k
^ permalink raw reply
* [PATCH 1/3] [POWERPC] Add docs for Freescale 83xx SATA device tree nodes
From: Kumar Gala @ 2007-11-21 5:12 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Li Yang
In-Reply-To: <Pine.LNX.4.64.0711202310280.24220@blarg.am.freescale.net>
---
Documentation/powerpc/booting-without-of.txt | 23 +++++++++++++++++++++++
1 files changed, 23 insertions(+), 0 deletions(-)
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index e9a3cb1..eb14dd5 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -2514,6 +2514,29 @@ platforms are moved over to use the flattened-device-tree model.
Requred properties:
- current-speed : Baud rate of uartlite
+ * Freescale 8xxx/3.0 Gb/s SATA nodes
+
+ SATA nodes are defined to describe on-chip Serial ATA controllers.
+ Each SATA port should have its own node.
+
+ Required properties:
+ - compatible : compatible list, contains 2 entries, first is
+ "fsl,sata-CHIP", where CHIP is the processor
+ (mpc8315, mpc8379, etc.) and the second is
+ "fsl,sata-pq2pro"
+ - interrupts : <interrupt mapping for SATA IRQ>
+ - interrupt-parent : optional, if needed for interrupt mapping
+ - reg : <registers mapping>
+
+ Example:
+
+ sata@19000 {
+ compatible = "fsl,mpc8315-sata", "fsl,sata-pq2pro;
+ reg = <19000 1000>;
+ interrupts = <2d 8>;
+ interrupt-parent = < &ipic >;
+ };
+
More devices will be defined as this spec matures.
VII - Specifying interrupt information for devices
--
1.5.3.4
^ permalink raw reply related
* [PATCH 2/3] [POWERPC] Add docs for Freescale RapidIO device tree node
From: Kumar Gala @ 2007-11-21 5:13 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <Pine.LNX.4.64.0711202310280.24220@blarg.am.freescale.net>
---
Documentation/powerpc/booting-without-of.txt | 47 ++++++++++++++++++++++++--
1 files changed, 44 insertions(+), 3 deletions(-)
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index eb14dd5..3d959d6 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -2521,9 +2521,9 @@ platforms are moved over to use the flattened-device-tree model.
Required properties:
- compatible : compatible list, contains 2 entries, first is
- "fsl,sata-CHIP", where CHIP is the processor
+ "fsl,CHIP-sata", where CHIP is the processor
(mpc8315, mpc8379, etc.) and the second is
- "fsl,sata-pq2pro"
+ "fsl,pq2pro-sata"
- interrupts : <interrupt mapping for SATA IRQ>
- interrupt-parent : optional, if needed for interrupt mapping
- reg : <registers mapping>
@@ -2531,12 +2531,53 @@ platforms are moved over to use the flattened-device-tree model.
Example:
sata@19000 {
- compatible = "fsl,mpc8315-sata", "fsl,sata-pq2pro;
+ compatible = "fsl,mpc8315-sata", "fsl,pq2pro-sata;
reg = <19000 1000>;
interrupts = <2d 8>;
interrupt-parent = < &ipic >;
};
+ * Frescale Serial RapidIO bus controller
+
+ RapidIO is a definition of a system interconnect. This node add
+ the support for RapidIO processor in kernel. The node name is
+ suggested to be 'rapidio'.
+
+ Required properties:
+
+ - compatible : compatible list, contains 2 entries, first is
+ "fsl,CHIP-rapidio", where CHIP is the processor
+ (mpc8572, mpc8641, etc.) and the second is
+ "fsl,delta-rapidio"
+ - interrupts : interrupts are expected in the following
+ order:
+ * Error/port write
+ * Outbound Doorbell
+ * Inbound Doorbell
+ * Outbound Msg Unit 1
+ * Inbound Msg Unit 1
+ * Outbound Msg Unit 2
+ * Inbound Msg Unit 2
+ - interrupt-parent : optional, if needed for interrupt mapping
+ - reg : <registers mapping>
+ - #address-cells : Should always be 2
+ - #size--cells : Should always be 2
+ - ranges : Details processor physical addr to RapidIO address
+
+ Example:
+
+ rapidio@c0000 {
+ compatible = "fsl,mpc8641-rapidio", "fsl,delta-rapidio;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ reg = <c0000 20000>;
+ ranges = <0 0 c0000000 20000000>;
+ interrupt-parent = <&mpic>;
+ /* err_irq bell_outb_irq bell_inb_irq msg1_tx_irq msg1_rx_irq
+ msg2_tx_irq msg2_rx_irq */
+ interrupts = <30 2 31 2 32 2 35 2 36 2 37 2 38 2>;
+ };
+
More devices will be defined as this spec matures.
VII - Specifying interrupt information for devices
--
1.5.3.4
^ permalink raw reply related
* [PATCH 3/3] [POWERPC] Add docs for Freescale DMA & DMA channel device tree nodes
From: Kumar Gala @ 2007-11-21 5:14 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <Pine.LNX.4.64.0711202310280.24220@blarg.am.freescale.net>
---
Documentation/powerpc/booting-without-of.txt | 113 ++++++++++++++++++++++++++
1 files changed, 113 insertions(+), 0 deletions(-)
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index 3d959d6..161fb0d 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -2578,6 +2578,119 @@ platforms are moved over to use the flattened-device-tree model.
interrupts = <30 2 31 2 32 2 35 2 36 2 37 2 38 2>;
};
+ * Freescale 83xx DMA Controller
+
+ Freescale PowerPC 83xx have on chip general purpose DMA controllers.
+
+ Required properties:
+
+ - compatible : compatible list, contains 2 entries, first is
+ "fsl,CHIP-dma", where CHIP is the processor
+ (mpc8349, mpc8360, etc.) and the second is
+ "fsl,elo-dma"
+ - reg : <registers mapping for DMA general status reg>
+ - ranges : Should be defined as specified in 1) to describe the
+ DMA controller channels.
+ - interrupts : <interrupt mapping for DMA IRQ>
+ - interrupt-parent : optional, if needed for interrupt mapping
+
+
+ - DMA channel nodes:
+ - compatible : compatible list, contains 2 entries, first is
+ "fsl,CHIP-dma-channel", where CHIP is the processor
+ (mpc8349, mpc8350, etc.) and the second is
+ "fsl,elo-dma-channel"
+ - reg : <registers mapping for channel>
+
+ Optional properties:
+ - interrupts : <interrupt mapping for DMA channel IRQ>
+ (on 83xx this is expected to be identical to
+ the interrupts property of the parent node)
+ - interrupt-parent : optional, if needed for interrupt mapping
+
+ Example:
+ dma@21000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8349-dma", "fsl,elo-dma";
+ reg = <21300 4>;
+ ranges = <0 21100 200>;
+ interrupt-parent = <&ipic>;
+ interrupts = <14 2>;
+ dma-channel@0 {
+ compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
+ reg = <0 80>;
+ };
+ dma-channel@80 {
+ compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
+ reg = <80 80>;
+ };
+ dma-channel@100 {
+ compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
+ reg = <100 80>;
+ };
+ dma-channel@180 {
+ compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
+ reg = <180 80>;
+ };
+ };
+
+ * Freescale 85xx DMA Controller
+
+ Freescale PowerPC 85xx have on chip general purpose DMA controllers.
+
+ Required properties:
+
+ - compatible : compatible list, contains 2 entries, first is
+ "fsl,CHIP-dma", where CHIP is the processor
+ (mpc8540, mpc8540, etc.) and the second is
+ "fsl,eloplus-dma"
+ - reg : <registers mapping for DMA general status reg>
+ - ranges : Should be defined as specified in 1) to describe the
+ DMA controller channels.
+
+ - DMA channel nodes:
+ - compatible : compatible list, contains 2 entries, first is
+ "fsl,CHIP-dma-channel", where CHIP is the processor
+ (mpc8540, mpc8560, etc.) and the second is
+ "fsl,eloplus-dma-channel"
+ - reg : <registers mapping for channel>
+ - interrupts : <interrupt mapping for DMA channel IRQ>
+ - interrupt-parent : optional, if needed for interrupt mapping
+
+ Example:
+ dma@21000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8540-dma", "fsl,eloplus-dma";
+ reg = <21300 4>;
+ ranges = <0 21100 200>;
+ dma-channel@0 {
+ compatible = "fsl,mpc8540-dma-channel", "fsl,eloplus-dma-channel";
+ reg = <0 80>;
+ interrupt-parent = <&mpic>;
+ interrupts = <14 2>;
+ };
+ dma-channel@80 {
+ compatible = "fsl,mpc8540-dma-channel", "fsl,eloplus-dma-channel";
+ reg = <80 80>;
+ interrupt-parent = <&mpic>;
+ interrupts = <15 2>;
+ };
+ dma-channel@100 {
+ compatible = "fsl,mpc8540-dma-channel", "fsl,eloplus-dma-channel";
+ reg = <100 80>;
+ interrupt-parent = <&mpic>;
+ interrupts = <16 2>;
+ };
+ dma-channel@180 {
+ compatible = "fsl,mpc8540-dma-channel", "fsl,eloplus-dma-channel";
+ reg = <180 80>;
+ interrupt-parent = <&mpic>;
+ interrupts = <17 2>;
+ };
+ };
+
More devices will be defined as this spec matures.
VII - Specifying interrupt information for devices
--
1.5.3.4
^ permalink raw reply related
* dtc: Flexible tree checking infrastructure
From: David Gibson @ 2007-11-21 5:38 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-dev
Here, at last, is a substantial start on revising dtc's infrastructure
for checking the tree; this is the rework I've been saying was
necessary practically since dtc was first release.
In the new model, we have a table of "check" structures, each with a
name, references to checking functions, and status variables. Each
check can (in principle) be individually switched off or on (as either
a warning or error). Checks have a list of prerequisites, so if
checks need to rely on results from earlier checks to make sense (or
even to avoid crashing) they just need to list the relevant other
checks there.
For now, only the "structural" checks and the fixups for phandle
references are converted to the new mechanism. The rather more
involved semantic checks (which is where this new mechanism will
really be useful) will have to be converted in future patches.
At present, there's no user interface for turning on/off the checks -
the -f option now forces output even if "error" level checks fail.
Again, future patches will be needed to add the fine-grained control,
but that should be quite straightforward with the infrastructure
implemented here.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Index: dtc/checks.c
===================================================================
--- dtc.orig/checks.c 2007-11-21 12:27:13.000000000 +1100
+++ dtc/checks.c 2007-11-21 16:28:08.000000000 +1100
@@ -20,104 +20,281 @@
#include "dtc.h"
-/*
- * Structural check functions
- */
+enum checklevel {
+ IGNORE = 0,
+ WARN = 1,
+ ERROR = 2,
+};
-#define ERRMSG(...) if (quiet < 2) fprintf(stderr, "ERROR: " __VA_ARGS__)
-#define WARNMSG(...) if (quiet < 1) fprintf(stderr, "Warning: " __VA_ARGS__)
+enum checkstatus {
+ UNCHECKED = 0,
+ PREREQ,
+ PASSED,
+ FAILED,
+};
-#define DO_ERR(...) do {ERRMSG(__VA_ARGS__); ok = 0; } while (0)
+struct check;
+
+typedef void (*tree_check_fn)(struct check *c, struct node *dt);
+typedef void (*node_check_fn)(struct check *c, struct node *dt, struct node *node);
+typedef void (*prop_check_fn)(struct check *c, struct node *dt,
+ struct node *node, struct property *prop);
+
+struct check {
+ const char *name;
+ tree_check_fn tree_fn;
+ node_check_fn node_fn;
+ prop_check_fn prop_fn;
+ void *data;
+ enum checklevel level;
+ enum checkstatus status;
+ int inprogress;
+ int num_prereqs;
+ struct check **prereq;
+};
-static int check_names(struct node *tree)
+#define CHECK(nm, tfn, nfn, pfn, d, lvl, ...) \
+ static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \
+ static struct check nm = { \
+ .name = #nm, \
+ .tree_fn = (tfn), \
+ .node_fn = (nfn), \
+ .prop_fn = (pfn), \
+ .data = (d), \
+ .level = (lvl), \
+ .status = UNCHECKED, \
+ .num_prereqs = ARRAY_SIZE(nm##_prereqs), \
+ .prereq = nm##_prereqs, \
+ };
+
+#define TREE_CHECK(nm, d, lvl, ...) \
+ CHECK(nm, check_##nm, NULL, NULL, d, lvl, __VA_ARGS__)
+#define NODE_CHECK(nm, d, lvl, ...) \
+ CHECK(nm, NULL, check_##nm, NULL, d, lvl, __VA_ARGS__)
+#define PROP_CHECK(nm, d, lvl, ...) \
+ CHECK(nm, NULL, NULL, check_##nm, d, lvl, __VA_ARGS__)
+#define BATCH_CHECK(nm, lvl, ...) \
+ CHECK(nm, NULL, NULL, NULL, NULL, lvl, __VA_ARGS__)
+
+#define CHECKMSG(c, fmt, ...) \
+ do { \
+ if (quiet < (c)->level) \
+ ; /* Suppress message */ \
+ else if ((c)->level == ERROR) \
+ fprintf(stderr, "ERROR (%s): " fmt "\n", \
+ (c)->name, __VA_ARGS__); \
+ else if ((c)->level == WARN) \
+ fprintf(stderr, "Warning (%s): " fmt "\n", \
+ (c)->name, __VA_ARGS__); \
+ } while (0)
+
+#define FAIL(c, fmt, ...) \
+ do { \
+ (c)->status = FAILED; \
+ CHECKMSG((c), fmt, __VA_ARGS__); \
+ } while (0)
+
+static void check_nodes_props(struct check *c, struct node *dt, struct node *node)
{
- struct node *child, *child2;
- struct property *prop, *prop2;
- int len = strlen(tree->name);
- int ok = 1;
+ struct node *child;
+ struct property *prop;
- if (len == 0 && tree->parent)
- DO_ERR("Empty, non-root nodename at %s\n", tree->fullpath);
+ if (c->node_fn)
+ c->node_fn(c, dt, node);
- if (len > MAX_NODENAME_LEN)
- WARNMSG("Overlength nodename at %s\n", tree->fullpath);
+ if (c->prop_fn)
+ for_each_property(node, prop)
+ c->prop_fn(c, dt, node, prop);
- for_each_property(tree, prop) {
- /* check for duplicates */
- /* FIXME: do this more efficiently */
- for (prop2 = prop->next; prop2; prop2 = prop2->next) {
- if (streq(prop->name, prop2->name)) {
- DO_ERR("Duplicate propertyname %s in node %s\n",
- prop->name, tree->fullpath);
- }
- }
+ for_each_child(node, child)
+ check_nodes_props(c, dt, child);
+}
+
+static int run_check(struct check *c, struct node *dt)
+{
+ int error = 0;
+ int i;
+
+ assert(!c->inprogress);
- /* check name length */
- if (strlen(prop->name) > MAX_PROPNAME_LEN)
- WARNMSG("Property name %s is too long in %s\n",
- prop->name, tree->fullpath);
+ if (c->status != UNCHECKED)
+ goto out;
+
+ c->inprogress = 1;
+
+ for (i = 0; i < c->num_prereqs; i++) {
+ struct check *prq = c->prereq[i];
+ error |= run_check(prq, dt);
+ if (prq->status != PASSED) {
+ c->status = PREREQ;
+ CHECKMSG(c, "Failed prerequisite '%s'",
+ c->prereq[i]->name);
+ }
}
- for_each_child(tree, child) {
- /* Check for duplicates */
+ if (c->status != UNCHECKED)
+ goto out;
+
+ if (c->node_fn || c->prop_fn)
+ check_nodes_props(c, dt, dt);
+
+ if (c->tree_fn)
+ c->tree_fn(c, dt);
+ if (c->status == UNCHECKED)
+ c->status = PASSED;
+
+out:
+ c->inprogress = 0;
+ if ((c->status != PASSED) && (c->level == ERROR))
+ error = 1;
+ return error;
+}
+
+/*
+ * Structural check functions
+ */
+
+static void check_duplicate_node_names(struct check *c, struct node *dt,
+ struct node *node)
+{
+ struct node *child, *child2;
+ for_each_child(node, child)
for (child2 = child->next_sibling;
child2;
- child2 = child2->next_sibling) {
+ child2 = child2->next_sibling)
if (streq(child->name, child2->name))
- DO_ERR("Duplicate node name %s\n",
- child->fullpath);
- }
- if (! check_names(child))
- ok = 0;
- }
+ FAIL(c, "Duplicate node name %s",
+ child->fullpath);
+}
+NODE_CHECK(duplicate_node_names, NULL, ERROR);
- return ok;
+static void check_duplicate_property_names(struct check *c, struct node *dt,
+ struct node *node)
+{
+ struct property *prop, *prop2;
+
+ for_each_property(node, prop)
+ for (prop2 = prop->next; prop2; prop2 = prop2->next)
+ if (streq(prop->name, prop2->name))
+ FAIL(c, "Duplicate property name %s in %s",
+ prop->name, node->fullpath);
}
+NODE_CHECK(duplicate_property_names, NULL, ERROR);
-static int check_phandles(struct node *root, struct node *node)
+static void check_explicit_phandles(struct check *c, struct node *root,
+ struct node *node)
{
struct property *prop;
- struct node *child, *other;
+ struct node *other;
cell_t phandle;
- int ok = 1;
prop = get_property(node, "linux,phandle");
- if (prop) {
- phandle = propval_cell(prop);
- if ((phandle == 0) || (phandle == -1)) {
- DO_ERR("%s has invalid linux,phandle %x\n",
- node->fullpath, phandle);
- } else {
- other = get_node_by_phandle(root, phandle);
- if (other)
- DO_ERR("%s has duplicated phandle %x (seen before at %s)\n",
- node->fullpath, phandle, other->fullpath);
+ if (! prop)
+ return; /* No phandle, that's fine */
- node->phandle = phandle;
- }
+ if (prop->val.len != sizeof(cell_t)) {
+ FAIL(c, "%s has bad length (%d) linux,phandle property",
+ node->fullpath, prop->val.len);
+ return;
}
- for_each_child(node, child)
- ok = ok && check_phandles(root, child);
+ phandle = propval_cell(prop);
+ if ((phandle == 0) || (phandle == -1)) {
+ FAIL(c, "%s has invalid linux,phandle value 0x%x",
+ node->fullpath, phandle);
+ return;
+ }
- return ok;
+ other = get_node_by_phandle(root, phandle);
+ if (other) {
+ FAIL(c, "%s has duplicated phandle 0x%x (seen before at %s)",
+ node->fullpath, phandle, other->fullpath);
+ return;
+ }
+
+ node->phandle = phandle;
}
+NODE_CHECK(explicit_phandles, NULL, ERROR);
+
+/*
+ * Reference fixup functions
+ */
-int check_structure(struct node *dt)
+static void fixup_references(struct check *c, struct node *dt,
+ struct node *node, struct property *prop)
{
- int ok = 1;
+ struct fixup *f = prop->val.refs;
+ struct node *refnode;
+ cell_t phandle;
+
+ while (f) {
+ if (f->ref[0] == '/') {
+ /* Reference to full path */
+ refnode = get_node_by_path(dt, f->ref);
+ if (! refnode)
+ FAIL(c, "Reference to non-existent node \"%s\"\n",
+ f->ref);
+ } else {
+ refnode = get_node_by_label(dt, f->ref);
+ if (! refnode)
+ FAIL(c, "Reference to non-existent node label \"%s\"\n",
+ f->ref);
+ }
+
+ phandle = get_node_phandle(dt, refnode);
+
+ assert(f->offset + sizeof(cell_t) <= prop->val.len);
+
+ *((cell_t *)(prop->val.val + f->offset)) = cpu_to_be32(phandle);
+
+ prop->val.refs = f->next;
+ fixup_free(f);
+ f = prop->val.refs;
+ }
+}
+CHECK(references, NULL, NULL, fixup_references, NULL, ERROR,
+ &duplicate_node_names, &explicit_phandles);
+
+static struct check *check_table[] = {
+ &duplicate_node_names, &duplicate_property_names,
+ &explicit_phandles,
+ &references,
+};
- ok = ok && check_names(dt);
- ok = ok && check_phandles(dt, dt);
+void process_checks(int force, struct node *dt)
+{
+ int i;
+ int error = 0;
- return ok;
+ for (i = 0; i < ARRAY_SIZE(check_table); i++) {
+ struct check *c = check_table[i];
+
+ if (c->level != IGNORE)
+ error = error || run_check(c, dt);
+ }
+
+ if (error) {
+ if (!force) {
+ fprintf(stderr, "ERROR: Input tree has errors, aborting "
+ "(use -f to force output)\n");
+ exit(2);
+ } else if (quiet < 3) {
+ fprintf(stderr, "Warning: Input tree has errors, "
+ "output forced\n");
+ }
+ }
}
/*
* Semantic check functions
*/
+#define ERRMSG(...) if (quiet < 2) fprintf(stderr, "ERROR: " __VA_ARGS__)
+#define WARNMSG(...) if (quiet < 1) fprintf(stderr, "Warning: " __VA_ARGS__)
+
+#define DO_ERR(...) do {ERRMSG(__VA_ARGS__); ok = 0; } while (0)
+
static int must_be_one_cell(struct property *prop, struct node *node)
{
if (prop->val.len != sizeof(cell_t)) {
Index: dtc/dtc.c
===================================================================
--- dtc.orig/dtc.c 2007-11-21 12:27:13.000000000 +1100
+++ dtc/dtc.c 2007-11-21 16:27:16.000000000 +1100
@@ -193,17 +193,7 @@ int main(int argc, char *argv[])
if (! bi || ! bi->dt)
die("Couldn't read input tree\n");
- structure_ok = check_structure(bi->dt);
- if (!structure_ok) {
- if (!force) {
- fprintf(stderr, "ERROR: Input tree has structural errors, aborting (use -f to force output)\n");
- exit(2);
- } else if (quiet < 3) {
- fprintf(stderr, "Warning: Input tree has structural errors, output forced\n");
- }
- }
-
- fixup_references(bi->dt);
+ process_checks(force, bi->dt);
if (check) {
if (!structure_ok) {
Index: dtc/dtc.h
===================================================================
--- dtc.orig/dtc.h 2007-11-21 12:27:13.000000000 +1100
+++ dtc/dtc.h 2007-11-21 16:27:16.000000000 +1100
@@ -193,9 +193,10 @@ char *get_unitname(struct node *node);
struct property *get_property(struct node *node, char *propname);
cell_t propval_cell(struct property *prop);
struct node *get_subnode(struct node *node, char *nodename);
+struct node *get_node_by_path(struct node *tree, char *path);
+struct node *get_node_by_label(struct node *tree, const char *label);
struct node *get_node_by_phandle(struct node *tree, cell_t phandle);
-
-void fixup_references(struct node *dt);
+cell_t get_node_phandle(struct node *root, struct node *node);
/* Boot info (tree plus memreserve information */
@@ -224,7 +225,7 @@ struct boot_info *build_boot_info(struct
/* Checks */
-int check_structure(struct node *dt);
+void process_checks(int force, struct node *dt);
int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys);
/* Flattened trees */
Index: dtc/livetree.c
===================================================================
--- dtc.orig/livetree.c 2007-11-21 16:27:09.000000000 +1100
+++ dtc/livetree.c 2007-11-21 16:27:16.000000000 +1100
@@ -216,7 +216,7 @@ struct node *get_subnode(struct node *no
return NULL;
}
-static struct node *get_node_by_path(struct node *tree, char *path)
+struct node *get_node_by_path(struct node *tree, char *path)
{
char *p;
struct node *child;
@@ -239,7 +239,7 @@ static struct node *get_node_by_path(str
return NULL;
}
-static struct node *get_node_by_label(struct node *tree, const char *label)
+struct node *get_node_by_label(struct node *tree, const char *label)
{
struct node *child, *node;
@@ -275,7 +275,7 @@ struct node *get_node_by_phandle(struct
return NULL;
}
-static cell_t get_node_phandle(struct node *root, struct node *node)
+cell_t get_node_phandle(struct node *root, struct node *node)
{
static cell_t phandle = 1; /* FIXME: ick, static local */
@@ -295,56 +295,3 @@ static cell_t get_node_phandle(struct no
return node->phandle;
}
-
-/*
- * Reference fixup functions
- */
-
-static void apply_fixup(struct node *root, struct property *prop,
- struct fixup *f)
-{
- struct node *refnode;
- cell_t phandle;
-
- if (f->ref[0] == '/') {
- /* Reference to full path */
- refnode = get_node_by_path(root, f->ref);
- if (! refnode)
- die("Reference to non-existent node \"%s\"\n", f->ref);
- } else {
- refnode = get_node_by_label(root, f->ref);
- if (! refnode)
- die("Reference to non-existent node label \"%s\"\n", f->ref);
- }
-
- phandle = get_node_phandle(root, refnode);
-
- assert(f->offset + sizeof(cell_t) <= prop->val.len);
-
- *((cell_t *)(prop->val.val + f->offset)) = cpu_to_be32(phandle);
-}
-
-static void fixup_phandles(struct node *root, struct node *node)
-{
- struct property *prop;
- struct node *child;
-
- for_each_property(node, prop) {
- struct fixup *f = prop->val.refs;
-
- while (f) {
- apply_fixup(root, prop, f);
- prop->val.refs = f->next;
- fixup_free(f);
- f = prop->val.refs;
- }
- }
-
- for_each_child(node, child)
- fixup_phandles(root, child);
-}
-
-void fixup_references(struct node *dt)
-{
- fixup_phandles(dt, dt);
-}
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* [PATCH 0/8] ibm_newemac: Candidate patches for 2.6.25
From: Benjamin Herrenschmidt @ 2007-11-21 6:06 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
Here are the patches I have pending for EMAC. With some non-released
patches from Hugh Blemings, I get a taishan (440GX) booting now,
in addition to Ebony (440GP) and various 405GP boards.
This is 2.6.25 material except for patch #1 which has already been
posted separately and is candidate for 2.6.24 (and possibly stable)
^ permalink raw reply
* [PATCH 1/8] ibm_newemac: Fix possible lockup on close
From: Benjamin Herrenschmidt @ 2007-11-21 6:06 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <1195625198.76200.922309668615.qpush@grosgo>
It's a bad idea to call flush_scheduled_work from within a
netdev->stop because the linkwatch will occasionally take the
rtnl lock from a workqueue context, and thus that can deadlock.
This reworks things a bit in that area to avoid the problem.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/net/ibm_newemac/core.c | 31 ++++++++++++++++++++-----------
drivers/net/ibm_newemac/core.h | 1 +
2 files changed, 21 insertions(+), 11 deletions(-)
Index: linux-work/drivers/net/ibm_newemac/core.c
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/core.c 2007-11-20 14:42:50.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/core.c 2007-11-20 14:46:51.000000000 +1100
@@ -642,9 +642,11 @@ static void emac_reset_work(struct work_
DBG(dev, "reset_work" NL);
mutex_lock(&dev->link_lock);
- emac_netif_stop(dev);
- emac_full_tx_reset(dev);
- emac_netif_start(dev);
+ if (dev->opened) {
+ emac_netif_stop(dev);
+ emac_full_tx_reset(dev);
+ emac_netif_start(dev);
+ }
mutex_unlock(&dev->link_lock);
}
@@ -1063,10 +1065,9 @@ static int emac_open(struct net_device *
dev->rx_sg_skb = NULL;
mutex_lock(&dev->link_lock);
+ dev->opened = 1;
- /* XXX Start PHY polling now. Shouldn't wr do like sungem instead and
- * always poll the PHY even when the iface is down ? That would allow
- * things like laptop-net to work. --BenH
+ /* Start PHY polling now.
*/
if (dev->phy.address >= 0) {
int link_poll_interval;
@@ -1145,9 +1146,11 @@ static void emac_link_timer(struct work_
int link_poll_interval;
mutex_lock(&dev->link_lock);
-
DBG2(dev, "link timer" NL);
+ if (!dev->opened)
+ goto bail;
+
if (dev->phy.def->ops->poll_link(&dev->phy)) {
if (!netif_carrier_ok(dev->ndev)) {
/* Get new link parameters */
@@ -1170,13 +1173,14 @@ static void emac_link_timer(struct work_
link_poll_interval = PHY_POLL_LINK_OFF;
}
schedule_delayed_work(&dev->link_work, link_poll_interval);
-
+ bail:
mutex_unlock(&dev->link_lock);
}
static void emac_force_link_update(struct emac_instance *dev)
{
netif_carrier_off(dev->ndev);
+ smp_rmb();
if (dev->link_polling) {
cancel_rearming_delayed_work(&dev->link_work);
if (dev->link_polling)
@@ -1191,11 +1195,14 @@ static int emac_close(struct net_device
DBG(dev, "close" NL);
- if (dev->phy.address >= 0)
+ if (dev->phy.address >= 0) {
+ dev->link_polling = 0;
cancel_rearming_delayed_work(&dev->link_work);
-
+ }
+ mutex_lock(&dev->link_lock);
emac_netif_stop(dev);
- flush_scheduled_work();
+ dev->opened = 0;
+ mutex_unlock(&dev->link_lock);
emac_rx_disable(dev);
emac_tx_disable(dev);
@@ -2756,6 +2763,8 @@ static int __devexit emac_remove(struct
unregister_netdev(dev->ndev);
+ flush_scheduled_work();
+
if (emac_has_feature(dev, EMAC_FTR_HAS_TAH))
tah_detach(dev->tah_dev, dev->tah_port);
if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII))
Index: linux-work/drivers/net/ibm_newemac/core.h
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/core.h 2007-11-20 14:42:50.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/core.h 2007-11-20 14:46:51.000000000 +1100
@@ -258,6 +258,7 @@ struct emac_instance {
int stop_timeout; /* in us */
int no_mcast;
int mcast_pending;
+ int opened;
struct work_struct reset_work;
spinlock_t lock;
};
^ permalink raw reply
* [PATCH 2/8] ibm_newemac: Add BCM5248 and Marvell 88E1111 PHY support
From: Benjamin Herrenschmidt @ 2007-11-21 6:06 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <1195625198.76200.922309668615.qpush@grosgo>
From: Stefan Roese <sr@denx.de>
This patch adds BCM5248 and Marvell 88E1111 PHY support to NEW EMAC driver.
These PHY chips are used on PowerPC 440EPx boards.
The PHY code is based on the previous work by Stefan Roese <sr@denx.de>
Signed-off-by: Stefan Roese <sr@denx.de>
Signed-off-by: Valentine Barshak <vbarshak@ru.mvista.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
--- linux.orig/drivers/net/ibm_newemac/phy.c 2007-06-15 21:45:18.000000000 +0400
+++ linux/drivers/net/ibm_newemac/phy.c 2007-06-15 20:45:15.000000000 +0400
@@ -306,8 +306,47 @@
.ops = &cis8201_phy_ops
};
+static struct mii_phy_def bcm5248_phy_def = {
+
+ .phy_id = 0x0143bc00,
+ .phy_id_mask = 0x0ffffff0,
+ .name = "BCM5248 10/100 SMII Ethernet",
+ .ops = &generic_phy_ops
+};
+
+static int m88e1111_init(struct mii_phy *phy)
+{
+ printk("%s: Marvell 88E1111 Ethernet\n", __FUNCTION__);
+ phy_write(phy, 0x14, 0x0ce3);
+ phy_write(phy, 0x18, 0x4101);
+ phy_write(phy, 0x09, 0x0e00);
+ phy_write(phy, 0x04, 0x01e1);
+ phy_write(phy, 0x00, 0x9140);
+ phy_write(phy, 0x00, 0x1140);
+
+ return 0;
+}
+
+static struct mii_phy_ops m88e1111_phy_ops = {
+ .init = m88e1111_init,
+ .setup_aneg = genmii_setup_aneg,
+ .setup_forced = genmii_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = genmii_read_link
+};
+
+static struct mii_phy_def m88e1111_phy_def = {
+
+ .phy_id = 0x01410CC0,
+ .phy_id_mask = 0x0ffffff0,
+ .name = "Marvell 88E1111 Ethernet",
+ .ops = &m88e1111_phy_ops,
+};
+
static struct mii_phy_def *mii_phy_table[] = {
&cis8201_phy_def,
+ &bcm5248_phy_def,
+ &m88e1111_phy_def,
&genmii_phy_def,
NULL
};
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* [PATCH 3/8] ibm_newemac: Add ET1011c PHY support
From: Benjamin Herrenschmidt @ 2007-11-21 6:06 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <1195625198.76200.922309668615.qpush@grosgo>
From: Stefan Roese <sr@denx.de>
This adds support for the Agere ET1011c PHY as found on the AMCC Taishan
board.
Signed-off-by: Stefan Roese <sr@denx.de>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/net/ibm_newemac/phy.c | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
Index: linux-work/drivers/net/ibm_newemac/phy.c
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/phy.c 2007-11-08 18:54:12.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/phy.c 2007-11-08 18:54:13.000000000 +1100
@@ -327,6 +327,42 @@ static int m88e1111_init(struct mii_phy
return 0;
}
+static int et1011c_init(struct mii_phy *phy)
+{
+ u16 reg_short;
+
+ reg_short = (u16)(phy_read(phy,0x16));
+ reg_short &= ~(0x7);
+ reg_short |= 0x6; /* RGMII Trace Delay*/
+ phy_write(phy, 0x16, reg_short);
+
+ reg_short = (u16)(phy_read(phy, 0x17));
+ reg_short &= ~(0x40);
+ phy_write(phy, 0x17, reg_short);
+
+ phy_write(phy,0x1c,0x74f0);
+ return 0;
+}
+
+static struct mii_phy_ops et1011c_phy_ops = {
+ .init = et1011c_init,
+ .setup_aneg = genmii_setup_aneg,
+ .setup_forced = genmii_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = genmii_read_link
+};
+
+static struct mii_phy_def et1011c_phy_def = {
+ .phy_id = 0x0282f000,
+ .phy_id_mask = 0x0fffff00,
+ .name = "ET1011C Gigabit Ethernet",
+ .ops = &et1011c_phy_ops
+};
+
+
+
+
+
static struct mii_phy_ops m88e1111_phy_ops = {
.init = m88e1111_init,
.setup_aneg = genmii_setup_aneg,
@@ -344,6 +380,7 @@ static struct mii_phy_def m88e1111_phy_d
};
static struct mii_phy_def *mii_phy_table[] = {
+ &et1011c_phy_def,
&cis8201_phy_def,
&bcm5248_phy_def,
&m88e1111_phy_def,
^ permalink raw reply
* [PATCH 4/8] ibm_newemac: Fix ZMII refcounting bug
From: Benjamin Herrenschmidt @ 2007-11-21 6:06 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <1195625198.76200.922309668615.qpush@grosgo>
When using ZMII for MDIO only (such as 440GX with RGMII for data and ZMII for
MDIO), the ZMII code would fail to properly refcount, thus triggering a
BUG_ON().
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Stefan Roese <sr@denx.de>
---
drivers/net/ibm_newemac/zmii.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
Index: linux-work/drivers/net/ibm_newemac/zmii.c
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/zmii.c 2007-11-08 15:45:32.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/zmii.c 2007-11-08 15:46:21.000000000 +1100
@@ -83,12 +83,14 @@ int __devinit zmii_attach(struct of_devi
ZMII_DBG(dev, "init(%d, %d)" NL, input, *mode);
- if (!zmii_valid_mode(*mode))
+ if (!zmii_valid_mode(*mode)) {
/* Probably an EMAC connected to RGMII,
* but it still may need ZMII for MDIO so
* we don't fail here.
*/
+ dev->users++;
return 0;
+ }
mutex_lock(&dev->lock);
^ permalink raw reply
* [PATCH 5/8] ibm_newemac: Workaround reset timeout when no link
From: Benjamin Herrenschmidt @ 2007-11-21 6:06 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <1195625198.76200.922309668615.qpush@grosgo>
With some PHYs, when the link goes away, the EMAC reset fails due
to the loss of the RX clock I believe.
The old EMAC driver worked around that using some internal chip-specific
clock force bits that are different on various 44x implementations.
This is an attempt at doing it differently, by avoiding the reset when
there is no link, but forcing loopback mode instead. It seems to work
on my Taishan 440GX based board so far.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Stefan Roese <sr@denx.de>
---
drivers/net/ibm_newemac/core.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
Index: linux-work/drivers/net/ibm_newemac/core.c
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/core.c 2007-11-20 14:46:51.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/core.c 2007-11-20 14:46:58.000000000 +1100
@@ -464,26 +464,34 @@ static int emac_configure(struct emac_in
{
struct emac_regs __iomem *p = dev->emacp;
struct net_device *ndev = dev->ndev;
- int tx_size, rx_size;
+ int tx_size, rx_size, link = netif_carrier_ok(dev->ndev);
u32 r, mr1 = 0;
DBG(dev, "configure" NL);
- if (emac_reset(dev) < 0)
+ if (!link) {
+ out_be32(&p->mr1, in_be32(&p->mr1)
+ | EMAC_MR1_FDE | EMAC_MR1_ILE);
+ udelay(100);
+ } else if (emac_reset(dev) < 0)
return -ETIMEDOUT;
if (emac_has_feature(dev, EMAC_FTR_HAS_TAH))
tah_reset(dev->tah_dev);
- DBG(dev, " duplex = %d, pause = %d, asym_pause = %d\n",
- dev->phy.duplex, dev->phy.pause, dev->phy.asym_pause);
+ DBG(dev, " link = %d duplex = %d, pause = %d, asym_pause = %d\n",
+ link, dev->phy.duplex, dev->phy.pause, dev->phy.asym_pause);
/* Default fifo sizes */
tx_size = dev->tx_fifo_size;
rx_size = dev->rx_fifo_size;
+ /* No link, force loopback */
+ if (!link)
+ mr1 = EMAC_MR1_FDE | EMAC_MR1_ILE;
+
/* Check for full duplex */
- if (dev->phy.duplex == DUPLEX_FULL)
+ else if (dev->phy.duplex == DUPLEX_FULL)
mr1 |= EMAC_MR1_FDE | EMAC_MR1_MWSW_001;
/* Adjust fifo sizes, mr1 and timeouts based on link speed */
@@ -1165,9 +1173,9 @@ static void emac_link_timer(struct work_
link_poll_interval = PHY_POLL_LINK_ON;
} else {
if (netif_carrier_ok(dev->ndev)) {
- emac_reinitialize(dev);
netif_carrier_off(dev->ndev);
netif_tx_disable(dev->ndev);
+ emac_reinitialize(dev);
emac_print_link_status(dev);
}
link_poll_interval = PHY_POLL_LINK_OFF;
^ permalink raw reply
* [PATCH 6/8] ibm_newemac: Cleanup/Fix RGMII MDIO support detection
From: Benjamin Herrenschmidt @ 2007-11-21 6:06 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <1195625198.76200.922309668615.qpush@grosgo>
More than just "AXON" version of EMAC RGMII supports MDIO, so replace
the current test with a generic property in the device-tree that
indicates such support.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Stefan Roese <sr@denx.de>
---
arch/powerpc/boot/dts/sequoia.dts | 1 +
drivers/net/ibm_newemac/rgmii.c | 20 +++++++++++---------
drivers/net/ibm_newemac/rgmii.h | 5 +++--
3 files changed, 15 insertions(+), 11 deletions(-)
Index: linux-work/drivers/net/ibm_newemac/rgmii.c
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/rgmii.c 2007-11-12 10:55:54.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/rgmii.c 2007-11-12 10:56:56.000000000 +1100
@@ -140,7 +140,7 @@ void rgmii_get_mdio(struct of_device *of
RGMII_DBG2(dev, "get_mdio(%d)" NL, input);
- if (dev->type != RGMII_AXON)
+ if (!(dev->flags & EMAC_RGMII_FLAG_HAS_MDIO))
return;
mutex_lock(&dev->lock);
@@ -161,7 +161,7 @@ void rgmii_put_mdio(struct of_device *of
RGMII_DBG2(dev, "put_mdio(%d)" NL, input);
- if (dev->type != RGMII_AXON)
+ if (!(dev->flags & EMAC_RGMII_FLAG_HAS_MDIO))
return;
fer = in_be32(&p->fer);
@@ -250,11 +250,13 @@ static int __devinit rgmii_probe(struct
goto err_free;
}
- /* Check for RGMII type */
+ /* Check for RGMII flags */
+ if (of_get_property(ofdev->node, "has-mdio", NULL))
+ dev->flags |= EMAC_RGMII_FLAG_HAS_MDIO;
+
+ /* CAB lacks the right properties, fix this up */
if (of_device_is_compatible(ofdev->node, "ibm,rgmii-axon"))
- dev->type = RGMII_AXON;
- else
- dev->type = RGMII_STANDARD;
+ dev->flags |= EMAC_RGMII_FLAG_HAS_MDIO;
DBG2(dev, " Boot FER = 0x%08x, SSR = 0x%08x\n",
in_be32(&dev->base->fer), in_be32(&dev->base->ssr));
@@ -263,9 +265,9 @@ static int __devinit rgmii_probe(struct
out_be32(&dev->base->fer, 0);
printk(KERN_INFO
- "RGMII %s %s initialized\n",
- dev->type == RGMII_STANDARD ? "standard" : "axon",
- ofdev->node->full_name);
+ "RGMII %s initialized with%s MDIO support\n",
+ ofdev->node->full_name,
+ (dev->flags & EMAC_RGMII_FLAG_HAS_MDIO) ? "" : "out");
wmb();
dev_set_drvdata(&ofdev->dev, dev);
Index: linux-work/drivers/net/ibm_newemac/rgmii.h
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/rgmii.h 2007-11-12 10:55:54.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/rgmii.h 2007-11-12 10:56:56.000000000 +1100
@@ -35,8 +35,9 @@ struct rgmii_regs {
struct rgmii_instance {
struct rgmii_regs __iomem *base;
- /* Type of RGMII bridge */
- int type;
+ /* RGMII bridge flags */
+ int flags;
+#define EMAC_RGMII_FLAG_HAS_MDIO 0x00000001
/* Only one EMAC whacks us at a time */
struct mutex lock;
Index: linux-work/arch/powerpc/boot/dts/sequoia.dts
===================================================================
--- linux-work.orig/arch/powerpc/boot/dts/sequoia.dts 2007-11-12 10:58:38.000000000 +1100
+++ linux-work/arch/powerpc/boot/dts/sequoia.dts 2007-11-12 10:58:47.000000000 +1100
@@ -245,6 +245,7 @@
device_type = "rgmii-interface";
compatible = "ibm,rgmii-440epx", "ibm,rgmii";
reg = <ef601000 8>;
+ has-mdio;
};
EMAC0: ethernet@ef600e00 {
^ permalink raw reply
* [PATCH 7/8] ibm_newemac: Cleanup/fix support for STACR register variants
From: Benjamin Herrenschmidt @ 2007-11-21 6:06 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <1195625198.76200.922309668615.qpush@grosgo>
There are a few variants of the STACR register that affect more than
just the "AXON" version of EMAC. Replace the current test of various
chip models with tests for generic properties in the device-tree.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Stefan Roese <sr@denx.de>
---
arch/powerpc/boot/dts/sequoia.dts | 4 ++++
drivers/net/ibm_newemac/core.c | 23 +++++++++++++----------
drivers/net/ibm_newemac/core.h | 6 +++---
3 files changed, 20 insertions(+), 13 deletions(-)
Index: linux-work/arch/powerpc/boot/dts/sequoia.dts
===================================================================
--- linux-work.orig/arch/powerpc/boot/dts/sequoia.dts 2007-11-20 14:47:01.000000000 +1100
+++ linux-work/arch/powerpc/boot/dts/sequoia.dts 2007-11-20 14:47:02.000000000 +1100
@@ -274,6 +274,8 @@
zmii-channel = <0>;
rgmii-device = <&RGMII0>;
rgmii-channel = <0>;
+ has-inverted-stacr-oc;
+ has-new-stacr-staopc;
};
EMAC1: ethernet@ef600f00 {
@@ -302,6 +304,8 @@
zmii-channel = <1>;
rgmii-device = <&RGMII0>;
rgmii-channel = <1>;
+ has-inverted-stacr-oc;
+ has-new-stacr-staopc;
};
};
};
Index: linux-work/drivers/net/ibm_newemac/core.c
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/core.c 2007-11-20 14:46:58.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/core.c 2007-11-20 14:47:02.000000000 +1100
@@ -711,7 +711,7 @@ static int __emac_mdio_read(struct emac_
r = EMAC_STACR_BASE(dev->opb_bus_freq);
if (emac_has_feature(dev, EMAC_FTR_STACR_OC_INVERT))
r |= EMAC_STACR_OC;
- if (emac_has_feature(dev, EMAC_FTR_HAS_AXON_STACR))
+ if (emac_has_feature(dev, EMAC_FTR_HAS_NEW_STACR))
r |= EMACX_STACR_STAC_READ;
else
r |= EMAC_STACR_STAC_READ;
@@ -783,7 +783,7 @@ static void __emac_mdio_write(struct ema
r = EMAC_STACR_BASE(dev->opb_bus_freq);
if (emac_has_feature(dev, EMAC_FTR_STACR_OC_INVERT))
r |= EMAC_STACR_OC;
- if (emac_has_feature(dev, EMAC_FTR_HAS_AXON_STACR))
+ if (emac_has_feature(dev, EMAC_FTR_HAS_NEW_STACR))
r |= EMACX_STACR_STAC_WRITE;
else
r |= EMAC_STACR_STAC_WRITE;
@@ -2480,16 +2480,19 @@ static int __devinit emac_init_config(st
/* Check EMAC version */
if (of_device_is_compatible(np, "ibm,emac4"))
dev->features |= EMAC_FTR_EMAC4;
- if (of_device_is_compatible(np, "ibm,emac-axon")
- || of_device_is_compatible(np, "ibm,emac-440epx"))
- dev->features |= EMAC_FTR_HAS_AXON_STACR
- | EMAC_FTR_STACR_OC_INVERT;
- if (of_device_is_compatible(np, "ibm,emac-440spe"))
+
+ /* Fixup some feature bits based on the device tree */
+ if (of_get_property(np, "has-inverted-stacr-oc", NULL))
dev->features |= EMAC_FTR_STACR_OC_INVERT;
+ if (of_get_property(np, "has-new-stacr-staopc", NULL))
+ dev->features |= EMAC_FTR_HAS_NEW_STACR;
- /* Fixup some feature bits based on the device tree and verify
- * we have support for them compiled in
- */
+ /* CAB lacks the appropriate properties */
+ if (of_device_is_compatible(np, "ibm,emac-axon"))
+ dev->features |= EMAC_FTR_HAS_NEW_STACR |
+ EMAC_FTR_STACR_OC_INVERT;
+
+ /* Enable TAH/ZMII/RGMII features as found */
if (dev->tah_ph != 0) {
#ifdef CONFIG_IBM_NEW_EMAC_TAH
dev->features |= EMAC_FTR_HAS_TAH;
Index: linux-work/drivers/net/ibm_newemac/core.h
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/core.h 2007-11-20 14:46:51.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/core.h 2007-11-20 14:47:02.000000000 +1100
@@ -293,9 +293,9 @@ struct emac_instance {
*/
#define EMAC_FTR_HAS_RGMII 0x00000020
/*
- * Set if we have axon-type STACR
+ * Set if we have new type STACR with STAOPC
*/
-#define EMAC_FTR_HAS_AXON_STACR 0x00000040
+#define EMAC_FTR_HAS_NEW_STACR 0x00000040
/* Right now, we don't quite handle the always/possible masks on the
@@ -307,7 +307,7 @@ enum {
EMAC_FTRS_POSSIBLE =
#ifdef CONFIG_IBM_NEW_EMAC_EMAC4
- EMAC_FTR_EMAC4 | EMAC_FTR_HAS_AXON_STACR |
+ EMAC_FTR_EMAC4 | EMAC_FTR_HAS_NEW_STACR |
EMAC_FTR_STACR_OC_INVERT |
#endif
#ifdef CONFIG_IBM_NEW_EMAC_TAH
^ permalink raw reply
* [PATCH 8/8] ibm_newemac: Skip EMACs that are marked unused by the firmware
From: Benjamin Herrenschmidt @ 2007-11-21 6:06 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <1195625198.76200.922309668615.qpush@grosgo>
From: Hugh Blemings <hugh@blemings.org>
Depending on how the 44x processors are wired, some EMAC cells
might not be useable (and not connected to a PHY). However, some
device-trees may choose to still expose them (since their registers
are present in the MMIO space) but with an "unused" property in them.
Signed-off-by: Hugh Blemings <hugh@blemings.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/net/ibm_newemac/core.c | 4 ++++
1 file changed, 4 insertions(+)
Index: linux-work/drivers/net/ibm_newemac/core.c
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/core.c 2007-11-20 14:47:02.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/core.c 2007-11-20 14:47:05.000000000 +1100
@@ -2550,6 +2550,10 @@ static int __devinit emac_probe(struct o
struct device_node **blist = NULL;
int err, i;
+ /* Skip unused/unwired EMACS */
+ if (of_get_property(np, "unused", NULL))
+ return -ENODEV;
+
/* Find ourselves in the bootlist if we are there */
for (i = 0; i < EMAC_BOOT_LIST_SIZE; i++)
if (emac_boot_list[i] == np)
^ permalink raw reply
* [PATCH 1/14] powerpc: Make isa_mem_base common to 32 and 64 bits
From: Benjamin Herrenschmidt @ 2007-11-21 6:14 UTC (permalink / raw)
To: linuxppc-dev
This defines isa_mem_base on both 32 and 64 bits (it used to be 32 bits
only). This avoids a few ifdef's in later patches and potentially can
allow support for VGA text mode on 64 bits powerpc.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
Small cleanup pre-requisite for my next patch
arch/powerpc/kernel/pci-common.c | 4 ++++
arch/powerpc/kernel/pci_32.c | 1 -
include/asm-powerpc/io.h | 5 +++--
3 files changed, 7 insertions(+), 3 deletions(-)
Index: linux-work/arch/powerpc/kernel/pci-common.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/pci-common.c 2007-11-20 14:42:49.000000000 +1100
+++ linux-work/arch/powerpc/kernel/pci-common.c 2007-11-20 15:03:02.000000000 +1100
@@ -52,6 +52,10 @@ int global_phb_number; /* Global phb co
extern struct list_head hose_list;
+/* ISA Memory physical address */
+resource_size_t isa_mem_base;
+
+
/*
* pci_controller(phb) initialized common variables.
*/
Index: linux-work/include/asm-powerpc/io.h
===================================================================
--- linux-work.orig/include/asm-powerpc/io.h 2007-11-20 14:42:49.000000000 +1100
+++ linux-work/include/asm-powerpc/io.h 2007-11-20 14:47:11.000000000 +1100
@@ -50,15 +50,16 @@ extern int check_legacy_ioport(unsigned
#define PCI_DRAM_OFFSET pci_dram_offset
#else
#define _IO_BASE pci_io_base
-#define _ISA_MEM_BASE 0
+#define _ISA_MEM_BASE isa_mem_base
#define PCI_DRAM_OFFSET 0
#endif
extern unsigned long isa_io_base;
-extern unsigned long isa_mem_base;
extern unsigned long pci_io_base;
extern unsigned long pci_dram_offset;
+extern resource_size_t isa_mem_base;
+
#if defined(CONFIG_PPC32) && defined(CONFIG_PPC_INDIRECT_IO)
#error CONFIG_PPC_INDIRECT_IO is not yet supported on 32 bits
#endif
Index: linux-work/arch/powerpc/kernel/pci_32.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/pci_32.c 2007-11-20 14:42:49.000000000 +1100
+++ linux-work/arch/powerpc/kernel/pci_32.c 2007-11-20 15:02:43.000000000 +1100
@@ -32,7 +32,6 @@
#endif
unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
unsigned long pci_dram_offset = 0;
int pcibios_assign_bus_offset = 1;
^ permalink raw reply
* [PATCH 2/14] powerpc: Merge pci_process_bridge_OF_ranges()
From: Benjamin Herrenschmidt @ 2007-11-21 6:14 UTC (permalink / raw)
To: linuxppc-dev
This patch merges the 32 and 64 bits implementations of
pci_process_bridge_OF_ranges(). The new function is cleaner than both
the old ones supports 64 bits ranges on ppc32 which is necessary for
the 4xx port.
It also adds some better (hopefully) output to the kernel log which
should help disagnose problems and makes better use of existing OF
parsing helpers (avoiding a few bugs of both implementations along
the way).
There are still a few unfortunate ifdef's but there is no way around
these for now at least not until some other bits of the PCI code are
made common.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
Tested on a few pSeries, PowerMac G5, and a 32 bits PowerMacs and
a BriQ. Please let me know if it misbehaves anywhere else.
arch/powerpc/kernel/pci-common.c | 176 +++++++++++++++++++++++++++++++++++++++
arch/powerpc/kernel/pci_32.c | 114 -------------------------
arch/powerpc/kernel/pci_64.c | 93 --------------------
include/asm-powerpc/pci-bridge.h | 1
4 files changed, 177 insertions(+), 207 deletions(-)
Index: linux-work/arch/powerpc/kernel/pci-common.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/pci-common.c 2007-11-13 14:15:43.000000000 +1100
+++ linux-work/arch/powerpc/kernel/pci-common.c 2007-11-13 16:04:06.000000000 +1100
@@ -479,3 +479,179 @@ void pci_resource_to_user(const struct p
*start = rsrc->start - offset;
*end = rsrc->end - offset;
}
+
+/**
+ * pci_process_bridge_OF_ranges - Parse PCI bridge resources from device tree
+ * @hose: newly allocated pci_controller to be setup
+ * @dev: device node of the host bridge
+ * @primary: set if primary bus (32 bits only, soon to be deprecated)
+ *
+ * This function will parse the "ranges" property of a PCI host bridge device
+ * node and setup the resource mapping of a pci controller based on its
+ * content.
+ *
+ * Life would be boring if it wasn't for a few issues that we have to deal
+ * with here:
+ *
+ * - We can only cope with one IO space range and up to 3 Memory space
+ * ranges. However, some machines (thanks Apple !) tend to split their
+ * space into lots of small contiguous ranges. So we have to coalesce.
+ *
+ * - We can only cope with all memory ranges having the same offset
+ * between CPU addresses and PCI addresses. Unfortunately, some bridges
+ * are setup for a large 1:1 mapping along with a small "window" which
+ * maps PCI address 0 to some arbitrary high address of the CPU space in
+ * order to give access to the ISA memory hole.
+ * The way out of here that I've chosen for now is to always set the
+ * offset based on the first resource found, then override it if we
+ * have a different offset and the previous was set by an ISA hole.
+ *
+ * - Some busses have IO space not starting at 0, which causes trouble with
+ * the way we do our IO resource renumbering. The code somewhat deals with
+ * it for 64 bits but I would expect problems on 32 bits.
+ *
+ * - Some 32 bits platforms such as 4xx can have physical space larger than
+ * 32 bits so we need to use 64 bits values for the parsing
+ */
+void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
+ struct device_node *dev,
+ int primary)
+{
+ const u32 *ranges;
+ int rlen;
+ int pna = of_n_addr_cells(dev);
+ int np = pna + 5;
+ int memno = 0, isa_hole = -1;
+ u32 pci_space;
+ unsigned long long pci_addr, cpu_addr, pci_next, cpu_next, size;
+ unsigned long long isa_mb = 0;
+ struct resource *res;
+
+ printk(KERN_INFO "PCI host bridge %s %s ranges:\n",
+ dev->full_name, primary ? "(primary)" : "");
+
+ /* Get ranges property */
+ ranges = of_get_property(dev, "ranges", &rlen);
+ if (ranges == NULL)
+ return;
+
+ /* Parse it */
+ while ((rlen -= np * 4) >= 0) {
+ /* Read next ranges element */
+ pci_space = ranges[0];
+ pci_addr = of_read_number(ranges + 1, 2);
+ cpu_addr = of_translate_address(dev, ranges + 3);
+ size = of_read_number(ranges + pna + 3, 2);
+ ranges += np;
+ if (cpu_addr == OF_BAD_ADDR || size == 0)
+ continue;
+
+ /* Now consume following elements while they are contiguous */
+ for (;rlen >= np * sizeof(u32); ranges += np, rlen -= np * 4) {
+ if (ranges[0] != pci_space)
+ break;
+ pci_next = of_read_number(ranges + 1, 2);
+ cpu_next = of_translate_address(dev, ranges + 3);
+ if (pci_next != pci_addr + size ||
+ cpu_next != cpu_addr + size)
+ break;
+ size += of_read_number(ranges + pna + 3, 2);
+ }
+
+ /* Act based on address space type */
+ res = NULL;
+ switch ((pci_space >> 24) & 0x3) {
+ case 1: /* PCI IO space */
+ printk(KERN_INFO
+ " IO 0x%016llx..0x%016llx -> 0x%016llx\n",
+ cpu_addr, cpu_addr + size - 1, pci_addr);
+
+ /* We support only one IO range */
+ if (hose->pci_io_size) {
+ printk(KERN_WARNING
+ " \\--> Skipped (too many) !\n");
+ continue;
+ }
+#ifdef CONFIG_PPC32
+ /* On 32 bits, limit I/O space to 16MB */
+ if (size > 0x01000000)
+ size = 0x01000000;
+
+ /* 32 bits needs to map IOs here */
+ hose->io_base_virt = ioremap(cpu_addr, size);
+
+ /* Expect trouble if pci_addr is not 0 */
+ if (primary)
+ isa_io_base =
+ (unsigned long)hose->io_base_virt;
+#endif /* CONFIG_PPC32 */
+ /* pci_io_size and io_base_phys always represent IO
+ * space starting at 0 so we factor in pci_addr
+ */
+ hose->pci_io_size = pci_addr + size;
+ hose->io_base_phys = cpu_addr - pci_addr;
+
+ /* Build resource */
+ res = &hose->io_resource;
+ res->flags = IORESOURCE_IO;
+ res->start = pci_addr;
+ break;
+ case 2: /* PCI Memory space */
+ printk(KERN_INFO
+ " MEM 0x%016llx..0x%016llx -> 0x%016llx %s\n",
+ cpu_addr, cpu_addr + size - 1, pci_addr,
+ (pci_space & 0x40000000) ? "Prefetch" : "");
+
+ /* We support only 3 memory ranges */
+ if (memno >= 3) {
+ printk(KERN_WARNING
+ " \\--> Skipped (too many) !\n");
+ continue;
+ }
+ /* Handles ISA memory hole space here */
+ if (pci_addr == 0) {
+ isa_mb = cpu_addr;
+ isa_hole = memno;
+ if (primary || isa_mem_base == 0)
+ isa_mem_base = cpu_addr;
+ }
+
+ /* We get the PCI/Mem offset from the first range or the,
+ * current one if the offset came from an ISA hole.
+ * If they don't match, bugger.
+ */
+ if (memno == 0 ||
+ (isa_hole >= 0 && pci_addr != 0 &&
+ hose->pci_mem_offset == isa_mb))
+ hose->pci_mem_offset = cpu_addr - pci_addr;
+ else if (pci_addr != 0 &&
+ hose->pci_mem_offset != cpu_addr - pci_addr) {
+ printk(KERN_WARNING
+ " \\--> Skipped (offset mismatch) !\n");
+ continue;
+ }
+
+ /* Build resource */
+ res = &hose->mem_resources[memno++];
+ res->flags = IORESOURCE_MEM;
+ if (pci_space & 0x40000000)
+ res->flags |= IORESOURCE_PREFETCH;
+ res->start = cpu_addr;
+ break;
+ }
+ if (res != NULL) {
+ res->name = dev->full_name;
+ res->end = res->start + size - 1;
+ res->parent = NULL;
+ res->sibling = NULL;
+ res->child = NULL;
+ }
+ }
+
+ /* Out of paranoia, let's put the ISA hole last if any */
+ if (isa_hole >= 0 && memno > 0 && isa_hole != (memno-1)) {
+ struct resource tmp = hose->mem_resources[isa_hole];
+ hose->mem_resources[isa_hole] = hose->mem_resources[memno-1];
+ hose->mem_resources[memno-1] = tmp;
+ }
+}
Index: linux-work/arch/powerpc/kernel/pci_32.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/pci_32.c 2007-11-13 14:16:17.000000000 +1100
+++ linux-work/arch/powerpc/kernel/pci_32.c 2007-11-13 14:16:24.000000000 +1100
@@ -842,120 +842,6 @@ pci_device_from_OF_node(struct device_no
}
EXPORT_SYMBOL(pci_device_from_OF_node);
-void __init
-pci_process_bridge_OF_ranges(struct pci_controller *hose,
- struct device_node *dev, int primary)
-{
- static unsigned int static_lc_ranges[256] __initdata;
- const unsigned int *dt_ranges;
- unsigned int *lc_ranges, *ranges, *prev, size;
- int rlen = 0, orig_rlen;
- int memno = 0;
- struct resource *res;
- int np, na = of_n_addr_cells(dev);
- np = na + 5;
-
- /* First we try to merge ranges to fix a problem with some pmacs
- * that can have more than 3 ranges, fortunately using contiguous
- * addresses -- BenH
- */
- dt_ranges = of_get_property(dev, "ranges", &rlen);
- if (!dt_ranges)
- return;
- /* Sanity check, though hopefully that never happens */
- if (rlen > sizeof(static_lc_ranges)) {
- printk(KERN_WARNING "OF ranges property too large !\n");
- rlen = sizeof(static_lc_ranges);
- }
- lc_ranges = static_lc_ranges;
- memcpy(lc_ranges, dt_ranges, rlen);
- orig_rlen = rlen;
-
- /* Let's work on a copy of the "ranges" property instead of damaging
- * the device-tree image in memory
- */
- ranges = lc_ranges;
- prev = NULL;
- while ((rlen -= np * sizeof(unsigned int)) >= 0) {
- if (prev) {
- if (prev[0] == ranges[0] && prev[1] == ranges[1] &&
- (prev[2] + prev[na+4]) == ranges[2] &&
- (prev[na+2] + prev[na+4]) == ranges[na+2]) {
- prev[na+4] += ranges[na+4];
- ranges[0] = 0;
- ranges += np;
- continue;
- }
- }
- prev = ranges;
- ranges += np;
- }
-
- /*
- * The ranges property is laid out as an array of elements,
- * each of which comprises:
- * cells 0 - 2: a PCI address
- * cells 3 or 3+4: a CPU physical address
- * (size depending on dev->n_addr_cells)
- * cells 4+5 or 5+6: the size of the range
- */
- ranges = lc_ranges;
- rlen = orig_rlen;
- while (ranges && (rlen -= np * sizeof(unsigned int)) >= 0) {
- res = NULL;
- size = ranges[na+4];
- switch ((ranges[0] >> 24) & 0x3) {
- case 1: /* I/O space */
- if (ranges[2] != 0)
- break;
- hose->io_base_phys = ranges[na+2];
- /* limit I/O space to 16MB */
- if (size > 0x01000000)
- size = 0x01000000;
- hose->io_base_virt = ioremap(ranges[na+2], size);
- if (primary)
- isa_io_base = (unsigned long) hose->io_base_virt;
- res = &hose->io_resource;
- res->flags = IORESOURCE_IO;
- res->start = ranges[2];
- DBG("PCI: IO 0x%llx -> 0x%llx\n",
- (u64)res->start, (u64)res->start + size - 1);
- break;
- case 2: /* memory space */
- memno = 0;
- if (ranges[1] == 0 && ranges[2] == 0
- && ranges[na+4] <= (16 << 20)) {
- /* 1st 16MB, i.e. ISA memory area */
- if (primary)
- isa_mem_base = ranges[na+2];
- memno = 1;
- }
- while (memno < 3 && hose->mem_resources[memno].flags)
- ++memno;
- if (memno == 0)
- hose->pci_mem_offset = ranges[na+2] - ranges[2];
- if (memno < 3) {
- res = &hose->mem_resources[memno];
- res->flags = IORESOURCE_MEM;
- if(ranges[0] & 0x40000000)
- res->flags |= IORESOURCE_PREFETCH;
- res->start = ranges[na+2];
- DBG("PCI: MEM[%d] 0x%llx -> 0x%llx\n", memno,
- (u64)res->start, (u64)res->start + size - 1);
- }
- break;
- }
- if (res != NULL) {
- res->name = dev->full_name;
- res->end = res->start + size - 1;
- res->parent = NULL;
- res->sibling = NULL;
- res->child = NULL;
- }
- ranges += np;
- }
-}
-
/* We create the "pci-OF-bus-map" property now so it appears in the
* /proc device tree
*/
Index: linux-work/arch/powerpc/kernel/pci_64.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/pci_64.c 2007-11-13 14:15:43.000000000 +1100
+++ linux-work/arch/powerpc/kernel/pci_64.c 2007-11-13 14:16:24.000000000 +1100
@@ -592,99 +592,6 @@ int pci_proc_domain(struct pci_bus *bus)
}
}
-void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
- struct device_node *dev, int prim)
-{
- const unsigned int *ranges;
- unsigned int pci_space;
- unsigned long size;
- int rlen = 0;
- int memno = 0;
- struct resource *res;
- int np, na = of_n_addr_cells(dev);
- unsigned long pci_addr, cpu_phys_addr;
-
- np = na + 5;
-
- /* From "PCI Binding to 1275"
- * The ranges property is laid out as an array of elements,
- * each of which comprises:
- * cells 0 - 2: a PCI address
- * cells 3 or 3+4: a CPU physical address
- * (size depending on dev->n_addr_cells)
- * cells 4+5 or 5+6: the size of the range
- */
- ranges = of_get_property(dev, "ranges", &rlen);
- if (ranges == NULL)
- return;
- hose->io_base_phys = 0;
- while ((rlen -= np * sizeof(unsigned int)) >= 0) {
- res = NULL;
- pci_space = ranges[0];
- pci_addr = ((unsigned long)ranges[1] << 32) | ranges[2];
- cpu_phys_addr = of_translate_address(dev, &ranges[3]);
- size = ((unsigned long)ranges[na+3] << 32) | ranges[na+4];
- ranges += np;
- if (size == 0)
- continue;
-
- /* Now consume following elements while they are contiguous */
- while (rlen >= np * sizeof(unsigned int)) {
- unsigned long addr, phys;
-
- if (ranges[0] != pci_space)
- break;
- addr = ((unsigned long)ranges[1] << 32) | ranges[2];
- phys = ranges[3];
- if (na >= 2)
- phys = (phys << 32) | ranges[4];
- if (addr != pci_addr + size ||
- phys != cpu_phys_addr + size)
- break;
-
- size += ((unsigned long)ranges[na+3] << 32)
- | ranges[na+4];
- ranges += np;
- rlen -= np * sizeof(unsigned int);
- }
-
- switch ((pci_space >> 24) & 0x3) {
- case 1: /* I/O space */
- hose->io_base_phys = cpu_phys_addr - pci_addr;
- /* handle from 0 to top of I/O window */
- hose->pci_io_size = pci_addr + size;
-
- res = &hose->io_resource;
- res->flags = IORESOURCE_IO;
- res->start = pci_addr;
- DBG("phb%d: IO 0x%lx -> 0x%lx\n", hose->global_number,
- res->start, res->start + size - 1);
- break;
- case 2: /* memory space */
- memno = 0;
- while (memno < 3 && hose->mem_resources[memno].flags)
- ++memno;
-
- if (memno == 0)
- hose->pci_mem_offset = cpu_phys_addr - pci_addr;
- if (memno < 3) {
- res = &hose->mem_resources[memno];
- res->flags = IORESOURCE_MEM;
- res->start = cpu_phys_addr;
- DBG("phb%d: MEM 0x%lx -> 0x%lx\n", hose->global_number,
- res->start, res->start + size - 1);
- }
- break;
- }
- if (res != NULL) {
- res->name = dev->full_name;
- res->end = res->start + size - 1;
- res->parent = NULL;
- res->sibling = NULL;
- res->child = NULL;
- }
- }
-}
#ifdef CONFIG_HOTPLUG
Index: linux-work/include/asm-powerpc/pci-bridge.h
===================================================================
--- linux-work.orig/include/asm-powerpc/pci-bridge.h 2007-11-13 14:15:43.000000000 +1100
+++ linux-work/include/asm-powerpc/pci-bridge.h 2007-11-13 14:16:24.000000000 +1100
@@ -27,6 +27,7 @@ struct pci_controller {
void __iomem *io_base_virt;
resource_size_t io_base_phys;
+ resource_size_t pci_io_size;
/* Some machines (PReP) have a non 1:1 mapping of
* the PCI memory space in the CPU bus space
^ permalink raw reply
* [PATCH 3/14] powerpc: Fix declaration of pcibios_free_controller
From: Benjamin Herrenschmidt @ 2007-11-21 6:14 UTC (permalink / raw)
To: linuxppc-dev
pcibios_free_controller() is now available for both 32 and 64 bits
but the header only declares it for 64 bits. This moves the
declaration down next to the pcibios_alloc_controller() one.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
include/asm-powerpc/pci-bridge.h | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
Index: linux-work/include/asm-powerpc/pci-bridge.h
===================================================================
--- linux-work.orig/include/asm-powerpc/pci-bridge.h 2007-11-16 13:44:32.000000000 +1100
+++ linux-work/include/asm-powerpc/pci-bridge.h 2007-11-16 13:46:40.000000000 +1100
@@ -247,7 +247,6 @@ static inline struct pci_controller *pci
return PCI_DN(busdn)->phb;
}
-extern void pcibios_free_controller(struct pci_controller *phb);
extern void isa_bridge_find_early(struct pci_controller *hose);
@@ -283,9 +282,11 @@ extern void
pci_process_bridge_OF_ranges(struct pci_controller *hose,
struct device_node *dev, int primary);
-/* Allocate a new PCI host bridge structure */
+/* Allocate & free a PCI host bridge structure */
extern struct pci_controller *
pcibios_alloc_controller(struct device_node *dev);
+extern void pcibios_free_controller(struct pci_controller *phb);
+
#ifdef CONFIG_PCI
extern unsigned long pci_address_to_pio(phys_addr_t address);
extern int pcibios_vaddr_is_ioport(void __iomem *address);
^ permalink raw reply
* [PATCH 4/14] powerpc: Fix powerpc 32 bits resource fixup for 64 bits resources
From: Benjamin Herrenschmidt @ 2007-11-21 6:14 UTC (permalink / raw)
To: linuxppc-dev
The 32bits powerpc resource fixup code uses unsigned longs to do the
offseting of resources which overflows on platforms such as 4xx where
resources can be 64 bits.
This fixes it by using resource_size_t instead.
However, the IO stuff does rely on some 32 bits arithmetic, so we hack
by cropping the result of the fixups for IO resources with a 32 bits
mask.
This isn't the prettiest but should work for now until we change the
32 bits PCI code to do IO mappings like 64 bits does, within a reserved
are of the kernel address space.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
This needs some regression testing.
arch/powerpc/kernel/pci_32.c | 44 +++++++++++++++++++++++--------------------
1 file changed, 24 insertions(+), 20 deletions(-)
Index: linux-work/arch/powerpc/kernel/pci_32.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/pci_32.c 2007-11-16 15:48:27.000000000 +1100
+++ linux-work/arch/powerpc/kernel/pci_32.c 2007-11-16 15:55:54.000000000 +1100
@@ -104,7 +104,7 @@ pcibios_fixup_resources(struct pci_dev *
{
struct pci_controller* hose = (struct pci_controller *)dev->sysdata;
int i;
- unsigned long offset;
+ resource_size_t offset, mask;
if (!hose) {
printk(KERN_ERR "No hose for PCI dev %s!\n", pci_name(dev));
@@ -123,15 +123,17 @@ pcibios_fixup_resources(struct pci_dev *
continue;
}
offset = 0;
+ mask = (resource_size_t)-1;
if (res->flags & IORESOURCE_MEM) {
offset = hose->pci_mem_offset;
} else if (res->flags & IORESOURCE_IO) {
offset = (unsigned long) hose->io_base_virt
- isa_io_base;
+ mask = 0xffffffffu;
}
if (offset != 0) {
- res->start += offset;
- res->end += offset;
+ res->start = (res->start + offset) & mask;
+ res->end = (res->end + offset) & mask;
DBG("Fixup res %d (%lx) of dev %s: %llx -> %llx\n",
i, res->flags, pci_name(dev),
(u64)res->start - offset, (u64)res->start);
@@ -147,30 +149,32 @@ DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PC
void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
struct resource *res)
{
- unsigned long offset = 0;
+ resource_size_t offset = 0, mask = (resource_size_t)-1;
struct pci_controller *hose = dev->sysdata;
- if (hose && res->flags & IORESOURCE_IO)
+ if (hose && res->flags & IORESOURCE_IO) {
offset = (unsigned long)hose->io_base_virt - isa_io_base;
- else if (hose && res->flags & IORESOURCE_MEM)
+ mask = 0xffffffffu;
+ } else if (hose && res->flags & IORESOURCE_MEM)
offset = hose->pci_mem_offset;
- region->start = res->start - offset;
- region->end = res->end - offset;
+ region->start = (res->start - offset) & mask;
+ region->end = (res->end - offset) & mask;
}
EXPORT_SYMBOL(pcibios_resource_to_bus);
void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
struct pci_bus_region *region)
{
- unsigned long offset = 0;
+ resource_size_t offset = 0, mask = (resource_size_t)-1;
struct pci_controller *hose = dev->sysdata;
- if (hose && res->flags & IORESOURCE_IO)
+ if (hose && res->flags & IORESOURCE_IO) {
offset = (unsigned long)hose->io_base_virt - isa_io_base;
- else if (hose && res->flags & IORESOURCE_MEM)
+ mask = 0xffffffffu;
+ } else if (hose && res->flags & IORESOURCE_MEM)
offset = hose->pci_mem_offset;
- res->start = region->start + offset;
- res->end = region->end + offset;
+ res->start = (region->start + offset) & mask;
+ res->end = (region->end + offset) & mask;
}
EXPORT_SYMBOL(pcibios_bus_to_resource);
@@ -334,9 +338,9 @@ static int __init
pci_relocate_bridge_resource(struct pci_bus *bus, int i)
{
struct resource *res, *pr, *conflict;
- unsigned long try, size;
- int j;
+ resource_size_t try, size;
struct pci_bus *parent = bus->parent;
+ int j;
if (parent == NULL) {
/* shouldn't ever happen */
@@ -438,7 +442,7 @@ update_bridge_resource(struct pci_dev *d
u8 io_base_lo, io_limit_lo;
u16 mem_base, mem_limit;
u16 cmd;
- unsigned long start, end, off;
+ resource_size_t start, end, off;
struct pci_controller *hose = dev->sysdata;
if (!hose) {
@@ -1157,8 +1161,8 @@ void pcibios_fixup_bus(struct pci_bus *b
res->end = IO_SPACE_LIMIT;
res->flags = IORESOURCE_IO;
}
- res->start += io_offset;
- res->end += io_offset;
+ res->start = (res->start + io_offset) & 0xffffffffu;
+ res->end = (res->end + io_offset) & 0xffffffffu;
for (i = 0; i < 3; ++i) {
res = &hose->mem_resources[i];
@@ -1183,8 +1187,8 @@ void pcibios_fixup_bus(struct pci_bus *b
if (!res->flags || bus->self->transparent)
continue;
if (io_offset && (res->flags & IORESOURCE_IO)) {
- res->start += io_offset;
- res->end += io_offset;
+ res->start = (res->start + io_offset) & 0xffffffffu;
+ res->end = (res->end + io_offset) & 0xffffffffu;
} else if (hose->pci_mem_offset
&& (res->flags & IORESOURCE_MEM)) {
res->start += hose->pci_mem_offset;
^ permalink raw reply
* [PATCH 5/14] powerpc: Fix 440/440A machine check handling
From: Benjamin Herrenschmidt @ 2007-11-21 6:15 UTC (permalink / raw)
To: linuxppc-dev
This removes CONFIG_440A which was a problem for multiplatform
kernels and instead fixes up the IVOR at runtime from a setup_cpu
function. The "A" version of the machine check also tweaks the
regs->trap value to differenciate the 2 versions at the C level.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/kernel/cpu_setup_44x.S | 4 +-
arch/powerpc/kernel/cputable.c | 5 +++
arch/powerpc/kernel/head_44x.S | 14 ++++++--
arch/powerpc/kernel/head_booke.h | 2 -
arch/powerpc/kernel/traps.c | 58 +++++++++++++++++++++++++++++-------
arch/powerpc/platforms/44x/Kconfig | 5 ---
include/asm-powerpc/ptrace.h | 3 +
include/asm-powerpc/reg_booke.h | 3 -
8 files changed, 70 insertions(+), 24 deletions(-)
Index: linux-work/arch/powerpc/kernel/cpu_setup_44x.S
===================================================================
--- linux-work.orig/arch/powerpc/kernel/cpu_setup_44x.S 2007-11-19 16:38:11.000000000 +1100
+++ linux-work/arch/powerpc/kernel/cpu_setup_44x.S 2007-11-19 16:58:25.000000000 +1100
@@ -23,11 +23,13 @@ _GLOBAL(__setup_cpu_440epx)
mflr r4
bl __init_fpu_44x
bl __plb_disable_wrp
+ bl __fixup_440A_mcheck
mtlr r4
blr
_GLOBAL(__setup_cpu_440grx)
b __plb_disable_wrp
-
+_GLOBAL(__setup_cpu_440gx)
+ b __fixup_440A_mcheck
/* enable APU between CPU and FPU */
_GLOBAL(__init_fpu_44x)
Index: linux-work/arch/powerpc/kernel/cputable.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/cputable.c 2007-11-19 16:36:53.000000000 +1100
+++ linux-work/arch/powerpc/kernel/cputable.c 2007-11-19 16:37:31.000000000 +1100
@@ -33,6 +33,7 @@ EXPORT_SYMBOL(cur_cpu_spec);
#ifdef CONFIG_PPC32
extern void __setup_cpu_440ep(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_440epx(unsigned long offset, struct cpu_spec* spec);
+extern void __setup_cpu_440gx(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_440grx(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec);
@@ -1193,6 +1194,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .cpu_setup = __setup_cpu_440gx,
.platform = "ppc440",
},
{ /* 440GX Rev. B */
@@ -1203,6 +1205,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .cpu_setup = __setup_cpu_440gx,
.platform = "ppc440",
},
{ /* 440GX Rev. C */
@@ -1213,6 +1216,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .cpu_setup = __setup_cpu_440gx,
.platform = "ppc440",
},
{ /* 440GX Rev. F */
@@ -1223,6 +1227,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .cpu_setup = __setup_cpu_440gx,
.platform = "ppc440",
},
{ /* 440SP Rev. A */
Index: linux-work/arch/powerpc/kernel/head_44x.S
===================================================================
--- linux-work.orig/arch/powerpc/kernel/head_44x.S 2007-11-19 16:41:48.000000000 +1100
+++ linux-work/arch/powerpc/kernel/head_44x.S 2007-11-19 16:58:53.000000000 +1100
@@ -289,11 +289,8 @@ interrupt_base:
CRITICAL_EXCEPTION(0x0100, CriticalInput, unknown_exception)
/* Machine Check Interrupt */
-#ifdef CONFIG_440A
- MCHECK_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
-#else
CRITICAL_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
-#endif
+ MCHECK_EXCEPTION(0x0210, MachineCheckA, machine_check_exception)
/* Data Storage Interrupt */
START_EXCEPTION(DataStorage)
@@ -674,6 +671,15 @@ finish_tlb_load:
*/
/*
+ * Adjust the machine check IVOR on 440A cores
+ */
+_GLOBAL(__fixup_440A_mcheck)
+ li r3,MachineCheckA@l
+ mtspr SPRN_IVOR1,r3
+ sync
+ blr
+
+/*
* extern void giveup_altivec(struct task_struct *prev)
*
* The 44x core does not have an AltiVec unit.
Index: linux-work/arch/powerpc/kernel/traps.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/traps.c 2007-11-19 16:44:07.000000000 +1100
+++ linux-work/arch/powerpc/kernel/traps.c 2007-11-19 17:19:44.000000000 +1100
@@ -334,18 +334,25 @@ static inline int check_io_access(struct
#define clear_single_step(regs) ((regs)->msr &= ~MSR_SE)
#endif
-static int generic_machine_check_exception(struct pt_regs *regs)
+#if defined(CONFIG_4xx)
+static int decode_machine_check_4xx(struct pt_regs *regs)
{
unsigned long reason = get_mc_reason(regs);
-#if defined(CONFIG_4xx) && !defined(CONFIG_440A)
if (reason & ESR_IMCP) {
printk("Instruction");
mtspr(SPRN_ESR, reason & ~ESR_IMCP);
} else
printk("Data");
printk(" machine check in kernel mode.\n");
-#elif defined(CONFIG_440A)
+
+ return 0;
+}
+
+static int decode_machine_check_4xxA(struct pt_regs *regs)
+{
+ unsigned long reason = get_mc_reason(regs);
+
printk("Machine check in kernel mode.\n");
if (reason & ESR_IMCP){
printk("Instruction Synchronous Machine Check exception\n");
@@ -375,7 +382,13 @@ static int generic_machine_check_excepti
/* Clear MCSR */
mtspr(SPRN_MCSR, mcsr);
}
-#elif defined (CONFIG_E500)
+ return 0;
+}
+#elif defined(CONFIG_E500)
+static int decode_machine_check_e500(struct pt_regs *regs)
+{
+ unsigned long reason = get_mc_reason(regs);
+
printk("Machine check in kernel mode.\n");
printk("Caused by (from MCSR=%lx): ", reason);
@@ -403,7 +416,14 @@ static int generic_machine_check_excepti
printk("Bus - Instruction Parity Error\n");
if (reason & MCSR_BUS_RPERR)
printk("Bus - Read Parity Error\n");
-#elif defined (CONFIG_E200)
+
+ return 0;
+}
+#elif defined(CONFIG_E200)
+static int decode_machine_check_e200(struct pt_regs *regs)
+{
+ unsigned long reason = get_mc_reason(regs);
+
printk("Machine check in kernel mode.\n");
printk("Caused by (from MCSR=%lx): ", reason);
@@ -421,7 +441,14 @@ static int generic_machine_check_excepti
printk("Bus - Read Bus Error on data load\n");
if (reason & MCSR_BUS_WRERR)
printk("Bus - Write Bus Error on buffered store or cache line push\n");
-#else /* !CONFIG_4xx && !CONFIG_E500 && !CONFIG_E200 */
+
+ return 0;
+}
+#else
+static int decode_machine_check_generic(struct pt_regs *regs)
+{
+ unsigned long reason = get_mc_reason(regs);
+
printk("Machine check in kernel mode.\n");
printk("Caused by (from SRR1=%lx): ", reason);
switch (reason & 0x601F0000) {
@@ -451,10 +478,9 @@ static int generic_machine_check_excepti
default:
printk("Unknown values in msr\n");
}
-#endif /* CONFIG_4xx */
-
return 0;
}
+#endif /* everything else */
void machine_check_exception(struct pt_regs *regs)
{
@@ -463,8 +489,20 @@ void machine_check_exception(struct pt_r
/* See if any machine dependent calls */
if (ppc_md.machine_check_exception)
recover = ppc_md.machine_check_exception(regs);
- else
- recover = generic_machine_check_exception(regs);
+ else {
+#ifdef CONFIG_4xx
+ if (IS_MCHECK_EXC(regs))
+ recover = decode_machine_check_4xxA(regs);
+ else
+ recover = decode_machine_check_4xx(regs);
+#elif defined (CONFIG_E500)
+ recover = decode_machine_check_e500(regs);
+#elif defined (CONFIG_E200)
+ recover = decode_machine_check_e200(regs);
+#else
+ recover = decode_machine_check_generic(regs);
+#endif
+ }
if (recover)
return;
Index: linux-work/arch/powerpc/platforms/44x/Kconfig
===================================================================
--- linux-work.orig/arch/powerpc/platforms/44x/Kconfig 2007-11-19 17:10:21.000000000 +1100
+++ linux-work/arch/powerpc/platforms/44x/Kconfig 2007-11-19 17:10:25.000000000 +1100
@@ -62,11 +62,6 @@ config 440GX
config 440SP
bool
-config 440A
- bool
- depends on 440GX || 440EPX
- default y
-
# 44x errata/workaround config symbols, selected by the CPU models above
config IBM440EP_ERR42
bool
Index: linux-work/arch/powerpc/kernel/head_booke.h
===================================================================
--- linux-work.orig/arch/powerpc/kernel/head_booke.h 2007-11-19 17:16:25.000000000 +1100
+++ linux-work/arch/powerpc/kernel/head_booke.h 2007-11-19 17:16:29.000000000 +1100
@@ -166,7 +166,7 @@ label:
mfspr r5,SPRN_ESR; \
stw r5,_ESR(r11); \
addi r3,r1,STACK_FRAME_OVERHEAD; \
- EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
+ EXC_XFER_TEMPLATE(hdlr, n+4, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
NOCOPY, mcheck_transfer_to_handler, \
ret_from_mcheck_exc)
Index: linux-work/include/asm-powerpc/ptrace.h
===================================================================
--- linux-work.orig/include/asm-powerpc/ptrace.h 2007-11-19 17:14:07.000000000 +1100
+++ linux-work/include/asm-powerpc/ptrace.h 2007-11-19 17:17:14.000000000 +1100
@@ -106,7 +106,8 @@ extern int ptrace_put_reg(struct task_st
*/
#define FULL_REGS(regs) (((regs)->trap & 1) == 0)
#ifndef __powerpc64__
-#define IS_CRITICAL_EXC(regs) (((regs)->trap & 2) == 0)
+#define IS_CRITICAL_EXC(regs) (((regs)->trap & 2) != 0)
+#define IS_MCHECK_EXC(regs) (((regs)->trap & 4) != 0)
#endif /* ! __powerpc64__ */
#define TRAP(regs) ((regs)->trap & ~0xF)
#ifdef __powerpc64__
Index: linux-work/include/asm-powerpc/reg_booke.h
===================================================================
--- linux-work.orig/include/asm-powerpc/reg_booke.h 2007-11-19 17:20:54.000000000 +1100
+++ linux-work/include/asm-powerpc/reg_booke.h 2007-11-19 17:20:59.000000000 +1100
@@ -207,7 +207,6 @@
#define CCR1_TCS 0x00000080 /* Timer Clock Select */
/* Bit definitions for the MCSR. */
-#ifdef CONFIG_440A
#define MCSR_MCS 0x80000000 /* Machine Check Summary */
#define MCSR_IB 0x40000000 /* Instruction PLB Error */
#define MCSR_DRB 0x20000000 /* Data Read PLB Error */
@@ -217,7 +216,7 @@
#define MCSR_DCSP 0x02000000 /* D-Cache Search Parity Error */
#define MCSR_DCFP 0x01000000 /* D-Cache Flush Parity Error */
#define MCSR_IMPE 0x00800000 /* Imprecise Machine Check Exception */
-#endif
+
#ifdef CONFIG_E500
#define MCSR_MCP 0x80000000UL /* Machine Check Input Pin */
#define MCSR_ICPERR 0x40000000UL /* I-Cache Parity Error */
^ permalink raw reply
* [PATCH 6/14] powerpc: Add xmon function to dump 44x TLB
From: Benjamin Herrenschmidt @ 2007-11-21 6:15 UTC (permalink / raw)
To: linuxppc-dev
This adds a function to xmon to dump the content of the 44x processor
TLB with a little bit of decoding (but not much).
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
Did that to track down some machine checks I was having while working
on PCI support due to 32/64 bits resource screwage.
Useful to see where a given MMIO virtual address really maps to.
arch/powerpc/xmon/xmon.c | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
Index: linux-work/arch/powerpc/xmon/xmon.c
===================================================================
--- linux-work.orig/arch/powerpc/xmon/xmon.c 2007-11-20 15:02:43.000000000 +1100
+++ linux-work/arch/powerpc/xmon/xmon.c 2007-11-20 17:04:48.000000000 +1100
@@ -153,6 +153,10 @@ static const char *getvecname(unsigned l
static int do_spu_cmd(void);
+#ifdef CONFIG_44x
+static void dump_tlb_44x(void);
+#endif
+
int xmon_no_auto_backtrace;
extern void xmon_enter(void);
@@ -231,6 +235,9 @@ Commands:\n\
#ifdef CONFIG_PPC_STD_MMU_32
" u dump segment registers\n"
#endif
+#ifdef CONFIG_44x
+" u dump TLB\n"
+#endif
" ? help\n"
" zr reboot\n\
zh halt\n"
@@ -856,6 +863,11 @@ cmds(struct pt_regs *excp)
dump_segments();
break;
#endif
+#ifdef CONFIG_44x
+ case 'u':
+ dump_tlb_44x();
+ break;
+#endif
default:
printf("Unrecognized command: ");
do {
@@ -2581,6 +2593,32 @@ void dump_segments(void)
}
#endif
+#ifdef CONFIG_44x
+static void dump_tlb_44x(void)
+{
+ int i;
+
+ for (i = 0; i < PPC44x_TLB_SIZE; i++) {
+ unsigned long w0,w1,w2;
+ asm volatile("tlbre %0,%1,0" : "=r" (w0) : "r" (i));
+ asm volatile("tlbre %0,%1,1" : "=r" (w1) : "r" (i));
+ asm volatile("tlbre %0,%1,2" : "=r" (w2) : "r" (i));
+ printf("[%02x] %08x %08x %08x ", i, w0, w1, w2);
+ if (w0 & PPC44x_TLB_VALID) {
+ printf("V %08x -> %01x%08x %c%c%c%c%c",
+ w0 & PPC44x_TLB_EPN_MASK,
+ w1 & PPC44x_TLB_ERPN_MASK,
+ w1 & PPC44x_TLB_RPN_MASK,
+ (w2 & PPC44x_TLB_W) ? 'W' : 'w',
+ (w2 & PPC44x_TLB_I) ? 'I' : 'i',
+ (w2 & PPC44x_TLB_M) ? 'M' : 'm',
+ (w2 & PPC44x_TLB_G) ? 'G' : 'g',
+ (w2 & PPC44x_TLB_E) ? 'E' : 'e');
+ }
+ printf("\n");
+ }
+}
+#endif /* CONFIG_44x */
void xmon_init(int enable)
{
#ifdef CONFIG_PPC_ISERIES
^ 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