* [RFC PATCH v2 03/12] of: Make of_find_node_by_path() traverse /aliases for relative paths.
2011-03-04 19:42 ` David Daney
@ 2011-03-04 19:42 ` David Daney
-1 siblings, 0 replies; 40+ messages in thread
From: David Daney @ 2011-03-04 19:42 UTC (permalink / raw)
To: linux-mips-6z/3iImG2C8G8FEW9MqTrA, ralf-6z/3iImG2C8G8FEW9MqTrA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
grant.likely-s3s/WqlpOiPyB63q8FvJNQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: David Daney
Currently all paths passed to of_find_node_by_path() must begin with a
'/', indicating a full path to the desired node.
Augment the look-up code so that if a path does *not* begin with '/',
the path is used as the name of an /aliases property. The value of
this alias is then used as the full node path to be found.
Signed-off-by: David Daney <ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8@public.gmane.org>
---
This patch is unchanged from the previous version I send separately. I
have not forgotten about Grant's feedback, just deferred it to the
next version.
drivers/of/base.c | 24 +++++++++++++++++++++++-
1 files changed, 23 insertions(+), 1 deletions(-)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 710b53b..e63da9c 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -340,7 +340,10 @@ EXPORT_SYMBOL(of_get_next_child);
/**
* of_find_node_by_path - Find a node matching a full OF path
- * @path: The full path to match
+ * @path: Either the full path to match, or if the path does not
+ * start with '/', the name of a property of the /aliases
+ * node (an alias). In the case of an alias, the node
+ * matching the alias' value will be returned.
*
* Returns a node pointer with refcount incremented, use
* of_node_put() on it when done.
@@ -348,13 +351,32 @@ EXPORT_SYMBOL(of_get_next_child);
struct device_node *of_find_node_by_path(const char *path)
{
struct device_node *np = allnodes;
+ struct device_node *aliases = NULL;
read_lock(&devtree_lock);
+
+ if (path[0] != '/') {
+ aliases = of_find_node_by_path("/aliases");
+ if (!aliases)
+ goto out;
+ path = of_get_property(aliases, path, NULL);
+ /*
+ * The alias must begin with '/', otherwise we could
+ * get stuck in an endless loop and blow out the
+ * stack.
+ */
+ if (!path || path[0] != '/')
+ goto out;
+ }
+
for (; np; np = np->allnext) {
if (np->full_name && (of_node_cmp(np->full_name, path) == 0)
&& of_node_get(np))
break;
}
+out:
+ if (aliases)
+ of_node_put(aliases);
read_unlock(&devtree_lock);
return np;
}
--
1.7.2.3
^ permalink raw reply related [flat|nested] 40+ messages in thread* [RFC PATCH v2 03/12] of: Make of_find_node_by_path() traverse /aliases for relative paths.
@ 2011-03-04 19:42 ` David Daney
0 siblings, 0 replies; 40+ messages in thread
From: David Daney @ 2011-03-04 19:42 UTC (permalink / raw)
To: linux-mips, ralf, devicetree-discuss, grant.likely, linux-kernel
Cc: David Daney
Currently all paths passed to of_find_node_by_path() must begin with a
'/', indicating a full path to the desired node.
Augment the look-up code so that if a path does *not* begin with '/',
the path is used as the name of an /aliases property. The value of
this alias is then used as the full node path to be found.
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
---
This patch is unchanged from the previous version I send separately. I
have not forgotten about Grant's feedback, just deferred it to the
next version.
drivers/of/base.c | 24 +++++++++++++++++++++++-
1 files changed, 23 insertions(+), 1 deletions(-)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 710b53b..e63da9c 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -340,7 +340,10 @@ EXPORT_SYMBOL(of_get_next_child);
/**
* of_find_node_by_path - Find a node matching a full OF path
- * @path: The full path to match
+ * @path: Either the full path to match, or if the path does not
+ * start with '/', the name of a property of the /aliases
+ * node (an alias). In the case of an alias, the node
+ * matching the alias' value will be returned.
*
* Returns a node pointer with refcount incremented, use
* of_node_put() on it when done.
@@ -348,13 +351,32 @@ EXPORT_SYMBOL(of_get_next_child);
struct device_node *of_find_node_by_path(const char *path)
{
struct device_node *np = allnodes;
+ struct device_node *aliases = NULL;
read_lock(&devtree_lock);
+
+ if (path[0] != '/') {
+ aliases = of_find_node_by_path("/aliases");
+ if (!aliases)
+ goto out;
+ path = of_get_property(aliases, path, NULL);
+ /*
+ * The alias must begin with '/', otherwise we could
+ * get stuck in an endless loop and blow out the
+ * stack.
+ */
+ if (!path || path[0] != '/')
+ goto out;
+ }
+
for (; np; np = np->allnext) {
if (np->full_name && (of_node_cmp(np->full_name, path) == 0)
&& of_node_get(np))
break;
}
+out:
+ if (aliases)
+ of_node_put(aliases);
read_unlock(&devtree_lock);
return np;
}
--
1.7.2.3
^ permalink raw reply related [flat|nested] 40+ messages in thread* Re: [RFC PATCH v2 03/12] of: Make of_find_node_by_path() traverse /aliases for relative paths.
2011-03-04 19:42 ` David Daney
(?)
@ 2011-03-04 21:55 ` Grant Likely
-1 siblings, 0 replies; 40+ messages in thread
From: Grant Likely @ 2011-03-04 21:55 UTC (permalink / raw)
To: David Daney; +Cc: linux-mips, ralf, devicetree-discuss, linux-kernel
On Fri, Mar 04, 2011 at 11:42:15AM -0800, David Daney wrote:
> Currently all paths passed to of_find_node_by_path() must begin with a
> '/', indicating a full path to the desired node.
>
> Augment the look-up code so that if a path does *not* begin with '/',
> the path is used as the name of an /aliases property. The value of
> this alias is then used as the full node path to be found.
>
> Signed-off-by: David Daney <ddaney@caviumnetworks.com>
> ---
>
> This patch is unchanged from the previous version I send separately. I
> have not forgotten about Grant's feedback, just deferred it to the
> next version.
okay; I'll wait for the next version before I consider picking it up.
g.
^ permalink raw reply [flat|nested] 40+ messages in thread
* [RFC PATCH v2 04/12] MIPS: Octeon: Add device tree source files.
2011-03-04 19:42 ` David Daney
@ 2011-03-04 19:42 ` David Daney
-1 siblings, 0 replies; 40+ messages in thread
From: David Daney @ 2011-03-04 19:42 UTC (permalink / raw)
To: linux-mips-6z/3iImG2C8G8FEW9MqTrA, ralf-6z/3iImG2C8G8FEW9MqTrA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
grant.likely-s3s/WqlpOiPyB63q8FvJNQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: David Daney
Signed-off-by: David Daney <ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8@public.gmane.org>
---
arch/mips/cavium-octeon/.gitignore | 2 +
arch/mips/cavium-octeon/Makefile | 13 ++
arch/mips/cavium-octeon/octeon_3xxx.dts | 330 +++++++++++++++++++++++++++++++
arch/mips/cavium-octeon/octeon_68xx.dts | 116 +++++++++++
4 files changed, 461 insertions(+), 0 deletions(-)
create mode 100644 arch/mips/cavium-octeon/.gitignore
create mode 100644 arch/mips/cavium-octeon/octeon_3xxx.dts
create mode 100644 arch/mips/cavium-octeon/octeon_68xx.dts
diff --git a/arch/mips/cavium-octeon/.gitignore b/arch/mips/cavium-octeon/.gitignore
new file mode 100644
index 0000000..39c9686
--- /dev/null
+++ b/arch/mips/cavium-octeon/.gitignore
@@ -0,0 +1,2 @@
+*.dtb.S
+*.dtb
diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile
index 19eb043..5e25dce 100644
--- a/arch/mips/cavium-octeon/Makefile
+++ b/arch/mips/cavium-octeon/Makefile
@@ -15,3 +15,16 @@ obj-y += octeon-memcpy.o
obj-y += executive/
obj-$(CONFIG_SMP) += smp.o
+
+DTS_FILES = octeon_3xxx.dts octeon_68xx.dts
+DTB_FILES = $(patsubst %.dts, %.dtb, $(DTS_FILES))
+
+obj-y += $(patsubst %.dts, %.dtb.o, $(DTS_FILES))
+
+$(obj)/%.dtb: $(src)/%.dts
+ $(call cmd,dtc)
+
+# Let's keep the .dtb files around in case we want to look at them.
+.SECONDARY: $(addprefix $(obj)/, $(DTB_FILES))
+
+clean-files += $(DTB_FILES) $(patsubst %.dtb, %.dtb.S, $(DTB_FILES))
diff --git a/arch/mips/cavium-octeon/octeon_3xxx.dts b/arch/mips/cavium-octeon/octeon_3xxx.dts
new file mode 100644
index 0000000..6910d9d
--- /dev/null
+++ b/arch/mips/cavium-octeon/octeon_3xxx.dts
@@ -0,0 +1,330 @@
+/dts-v1/;
+/*
+ * OCTEON 3XXX, 5XXX, 63XX device tree skeleton.
+ *
+ * This device tree is pruned and patched by early boot code before
+ * use. Because of this, it contains a super-set of the available
+ * devices and properties.
+ */
+/ {
+ model = "OCTEON";
+ compatible = "cavium,octeon-3860";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ soc@0 {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges; /* Direct mapping */
+
+ ciu: interrupt-controller@1070000000000 {
+ compatible = "cavium,octeon-3860-ciu";
+ interrupt-controller;
+ #address-cells = <0>;
+ /* Interrupts are specified by three parts:
+ * 1) Controller register (0 or 1)
+ * 2) Bit within the register (0..63)
+ * 3) Triggering (0 - level active high
+ * 1 - level active low
+ * 2 - edge rising
+ * 3 - edge falling
+ *
+ * For non-GPIO sources, the triggering cannot be
+ * changed and is ignored.
+ */
+ #interrupt-cells = <3>;
+ reg = <0x10700 0x00000000 0x0 0x7000>;
+ };
+
+ smi0: mdio@1180000001800 {
+ compatible = "cavium,octeon-3860-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x11800 0x00001800 0x0 0x40>;
+
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ };
+
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+
+ phy2: ethernet-phy@2 {
+ reg = <2>;
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ };
+ phy3: ethernet-phy@3 {
+ reg = <3>;
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ };
+ phy4: ethernet-phy@4 {
+ reg = <4>;
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ };
+ phy5: ethernet-phy@5 {
+ reg = <5>;
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ };
+
+ phy6: ethernet-phy@6 {
+ reg = <6>;
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ };
+ phy7: ethernet-phy@7 {
+ reg = <7>;
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ };
+ phy8: ethernet-phy@8 {
+ reg = <8>;
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ };
+ phy9: ethernet-phy@9 {
+ reg = <9>;
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ };
+ };
+
+ smi1: mdio@1180000001900 {
+ compatible = "cavium,octeon-3860-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x11800 0x00001900 0x0 0x40>;
+ };
+
+ mix0: ethernet@1070000100000 {
+ compatible = "cavium,octeon-5750-mix";
+ device_type = "network";
+ reg = <0x10700 0x00100000 0x0 0x100>, /* MIX */
+ <0x11800 0xE0000000 0x0 0x300>, /* AGL */
+ <0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED */
+ <0x11800 0xE0002000 0x0 0x8>; /* AGL_PRT_CTL */
+ cell-index = <0>;
+ interrupt-parent = <&ciu>;
+ interrupts = <0 62 0>, <1 46 0>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ phy-handle = <&phy0>;
+ };
+
+ mix1: ethernet@1070000100800 {
+ compatible = "cavium,octeon-5750-mix";
+ device_type = "network";
+ reg = <0x10700 0x00100800 0x0 0x100>, /* MIX */
+ <0x11800 0xE0000800 0x0 0x300>, /* AGL */
+ <0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED */
+ <0x11800 0xE0002008 0x0 0x8>; /* AGL_PRT_CTL */
+ cell-index = <1>;
+ interrupt-parent = <&ciu>;
+ interrupts = <1 18 0>, < 1 46 0>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ phy-handle = <&phy1>;
+ };
+
+ pip: pip@11800a0000000 {
+ compatible = "cavium,octeon-3860-pip";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x11800 0xa0000000 0x0 0x2000>;
+
+ interface@0 {
+ compatible = "cavium,octeon-3860-pip-interface";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>; /* interface */
+
+ ethernet@0 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x0>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ phy-handle = <&phy2>;
+ };
+ ethernet@1 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x1>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ phy-handle = <&phy3>;
+ };
+ ethernet@2 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x2>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ phy-handle = <&phy4>;
+ };
+ ethernet@3 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x3>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ phy-handle = <&phy5>;
+ };
+ };
+
+ interface@1 {
+ compatible = "cavium,octeon-3860-pip-interface";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>; /* interface */
+
+ ethernet@0 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x0>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ phy-handle = <&phy6>;
+ };
+ ethernet@1 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x1>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ phy-handle = <&phy7>;
+ };
+ ethernet@2 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x2>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ phy-handle = <&phy8>;
+ };
+ ethernet@3 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x3>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ phy-handle = <&phy9>;
+ };
+ };
+
+ interface@2 { /* DPI interface. */
+ compatible = "cavium,octeon-3860-pip-interface";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>; /* interface */
+
+ ethernet@0 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x0>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+ ethernet@1 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x1>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+ ethernet@2 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x2>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+ ethernet@3 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x3>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+ };
+
+ interface@3 { /* Loop interface. */
+ compatible = "cavium,octeon-3860-pip-interface";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>; /* interface */
+
+ ethernet@0 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x0>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+ ethernet@1 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x1>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+ ethernet@2 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x2>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+ ethernet@3 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x3>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+ };
+ };
+
+ twsi0: i2c@1180000001000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "cavium,octeon-3860-twsi";
+ reg = <0x11800 0x00001000 0x0 0x200>;
+ interrupt-parent = <&ciu>;
+ interrupts = <0 45 0>;
+ clock-rate = <100000>;
+
+ rtc@68 {
+ compatible = "dallas,ds1337";
+ reg = <0x68>;
+ };
+ tmp@4c {
+ compatible = "ti,tmp421";
+ reg = <0x4c>;
+ };
+ };
+
+ twsi1: i2c@1180000001200 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "cavium,octeon-3860-twsi";
+ reg = <0x11800 0x00001200 0x0 0x200>;
+ interrupt-parent = <&ciu>;
+ interrupts = <0 59 0>;
+ clock-rate = <100000>;
+ };
+ };
+
+ aliases {
+ mix0 = &mix0;
+ mix1 = &mix1;
+ pip = &pip;
+ smi0 = &smi0;
+ smi1 = &smi1;
+ twsi0 = &twsi0;
+ twsi1 = &twsi1;
+ };
+ };
diff --git a/arch/mips/cavium-octeon/octeon_68xx.dts b/arch/mips/cavium-octeon/octeon_68xx.dts
new file mode 100644
index 0000000..f2a8eab
--- /dev/null
+++ b/arch/mips/cavium-octeon/octeon_68xx.dts
@@ -0,0 +1,116 @@
+/dts-v1/;
+/*
+ * OCTEON 68XX device tree skeleton.
+ */
+/ {
+ model = "OCTEON";
+ compatible = "cavium,octeon-6880";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ soc@0 {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges; /* Direct mapping */
+
+ ciu2: interrupt-controller@1070100000000 {
+ compatible = "cavium,octeon-6880-ciu2";
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ reg = <0x10701 0x00000000 0x0 0x4000000>;
+ };
+
+ smi0: mdio@1180000003800 {
+ compatible = "cavium,octeon-3860-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x11800 0x00003800 0x0 0x40>;
+
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ device_type = "ethernet-phy";
+ };
+
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ device_type = "ethernet-phy";
+ };
+
+ phy3: ethernet-phy@3 {
+ reg = <3>;
+ device_type = "ethernet-phy";
+ };
+ };
+
+ smi1: mdio@1180000003880 {
+ compatible = "cavium,octeon-3860-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x11800 0x00003880 0x0 0x40>;
+ };
+
+ smi2: mdio@1180000003900 {
+ compatible = "cavium,octeon-3860-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x11800 0x00003900 0x0 0x40>;
+ };
+
+ smi3: mdio@1180000003980 {
+ compatible = "cavium,octeon-3860-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x11800 0x00003980 0x0 0x40>;
+ };
+
+ mix0: ethernet@1070000100000 {
+ compatible = "cavium,octeon-5750-mix";
+ device_type = "network";
+ reg = <0x10700 0x00100000 0x0 0x100>, /* MIX */
+ <0x11800 0xE0000000 0x0 0x300>, /* AGL */
+ <0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED */
+ <0x11800 0xE0002000 0x0 0x8>; /* AGL_PRT_CTL */
+ cell-index = <0>;
+ interrupt-parent = <&ciu2>;
+ interrupts = <0 62>, <1 46>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ phy-handle = <&phy0>;
+ };
+
+ twsi0: i2c@1180000001000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "cavium,octeon-3860-twsi";
+ reg = <0x11800 0x00001000 0x0 0x200>;
+ interrupt-parent = <&ciu2>;
+ interrupts = <0 45>;
+ clock-rate = <100000>;
+
+ rtc@68 {
+ compatible = "dallas,ds1337";
+ reg = <0x68>;
+ };
+ };
+
+ twsi1: i2c@1180000001200 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "cavium,octeon-3860-twsi";
+ reg = <0x11800 0x00001200 0x0 0x200>;
+ interrupt-parent = <&ciu2>;
+ interrupts = <0 59>;
+ clock-rate = <100000>;
+ };
+ };
+ aliases {
+ mix0 = &mix0;
+ smi0 = &smi0;
+ smi1 = &smi1;
+ smi2 = &smi2;
+ smi3 = &smi3;
+ twsi0 = &twsi0;
+ twsi1 = &twsi1;
+ };
+ };
--
1.7.2.3
^ permalink raw reply related [flat|nested] 40+ messages in thread* [RFC PATCH v2 04/12] MIPS: Octeon: Add device tree source files.
@ 2011-03-04 19:42 ` David Daney
0 siblings, 0 replies; 40+ messages in thread
From: David Daney @ 2011-03-04 19:42 UTC (permalink / raw)
To: linux-mips, ralf, devicetree-discuss, grant.likely, linux-kernel
Cc: David Daney
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
---
arch/mips/cavium-octeon/.gitignore | 2 +
arch/mips/cavium-octeon/Makefile | 13 ++
arch/mips/cavium-octeon/octeon_3xxx.dts | 330 +++++++++++++++++++++++++++++++
arch/mips/cavium-octeon/octeon_68xx.dts | 116 +++++++++++
4 files changed, 461 insertions(+), 0 deletions(-)
create mode 100644 arch/mips/cavium-octeon/.gitignore
create mode 100644 arch/mips/cavium-octeon/octeon_3xxx.dts
create mode 100644 arch/mips/cavium-octeon/octeon_68xx.dts
diff --git a/arch/mips/cavium-octeon/.gitignore b/arch/mips/cavium-octeon/.gitignore
new file mode 100644
index 0000000..39c9686
--- /dev/null
+++ b/arch/mips/cavium-octeon/.gitignore
@@ -0,0 +1,2 @@
+*.dtb.S
+*.dtb
diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile
index 19eb043..5e25dce 100644
--- a/arch/mips/cavium-octeon/Makefile
+++ b/arch/mips/cavium-octeon/Makefile
@@ -15,3 +15,16 @@ obj-y += octeon-memcpy.o
obj-y += executive/
obj-$(CONFIG_SMP) += smp.o
+
+DTS_FILES = octeon_3xxx.dts octeon_68xx.dts
+DTB_FILES = $(patsubst %.dts, %.dtb, $(DTS_FILES))
+
+obj-y += $(patsubst %.dts, %.dtb.o, $(DTS_FILES))
+
+$(obj)/%.dtb: $(src)/%.dts
+ $(call cmd,dtc)
+
+# Let's keep the .dtb files around in case we want to look at them.
+.SECONDARY: $(addprefix $(obj)/, $(DTB_FILES))
+
+clean-files += $(DTB_FILES) $(patsubst %.dtb, %.dtb.S, $(DTB_FILES))
diff --git a/arch/mips/cavium-octeon/octeon_3xxx.dts b/arch/mips/cavium-octeon/octeon_3xxx.dts
new file mode 100644
index 0000000..6910d9d
--- /dev/null
+++ b/arch/mips/cavium-octeon/octeon_3xxx.dts
@@ -0,0 +1,330 @@
+/dts-v1/;
+/*
+ * OCTEON 3XXX, 5XXX, 63XX device tree skeleton.
+ *
+ * This device tree is pruned and patched by early boot code before
+ * use. Because of this, it contains a super-set of the available
+ * devices and properties.
+ */
+/ {
+ model = "OCTEON";
+ compatible = "cavium,octeon-3860";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ soc@0 {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges; /* Direct mapping */
+
+ ciu: interrupt-controller@1070000000000 {
+ compatible = "cavium,octeon-3860-ciu";
+ interrupt-controller;
+ #address-cells = <0>;
+ /* Interrupts are specified by three parts:
+ * 1) Controller register (0 or 1)
+ * 2) Bit within the register (0..63)
+ * 3) Triggering (0 - level active high
+ * 1 - level active low
+ * 2 - edge rising
+ * 3 - edge falling
+ *
+ * For non-GPIO sources, the triggering cannot be
+ * changed and is ignored.
+ */
+ #interrupt-cells = <3>;
+ reg = <0x10700 0x00000000 0x0 0x7000>;
+ };
+
+ smi0: mdio@1180000001800 {
+ compatible = "cavium,octeon-3860-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x11800 0x00001800 0x0 0x40>;
+
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ };
+
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+
+ phy2: ethernet-phy@2 {
+ reg = <2>;
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ };
+ phy3: ethernet-phy@3 {
+ reg = <3>;
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ };
+ phy4: ethernet-phy@4 {
+ reg = <4>;
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ };
+ phy5: ethernet-phy@5 {
+ reg = <5>;
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ };
+
+ phy6: ethernet-phy@6 {
+ reg = <6>;
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ };
+ phy7: ethernet-phy@7 {
+ reg = <7>;
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ };
+ phy8: ethernet-phy@8 {
+ reg = <8>;
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ };
+ phy9: ethernet-phy@9 {
+ reg = <9>;
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ };
+ };
+
+ smi1: mdio@1180000001900 {
+ compatible = "cavium,octeon-3860-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x11800 0x00001900 0x0 0x40>;
+ };
+
+ mix0: ethernet@1070000100000 {
+ compatible = "cavium,octeon-5750-mix";
+ device_type = "network";
+ reg = <0x10700 0x00100000 0x0 0x100>, /* MIX */
+ <0x11800 0xE0000000 0x0 0x300>, /* AGL */
+ <0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED */
+ <0x11800 0xE0002000 0x0 0x8>; /* AGL_PRT_CTL */
+ cell-index = <0>;
+ interrupt-parent = <&ciu>;
+ interrupts = <0 62 0>, <1 46 0>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ phy-handle = <&phy0>;
+ };
+
+ mix1: ethernet@1070000100800 {
+ compatible = "cavium,octeon-5750-mix";
+ device_type = "network";
+ reg = <0x10700 0x00100800 0x0 0x100>, /* MIX */
+ <0x11800 0xE0000800 0x0 0x300>, /* AGL */
+ <0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED */
+ <0x11800 0xE0002008 0x0 0x8>; /* AGL_PRT_CTL */
+ cell-index = <1>;
+ interrupt-parent = <&ciu>;
+ interrupts = <1 18 0>, < 1 46 0>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ phy-handle = <&phy1>;
+ };
+
+ pip: pip@11800a0000000 {
+ compatible = "cavium,octeon-3860-pip";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x11800 0xa0000000 0x0 0x2000>;
+
+ interface@0 {
+ compatible = "cavium,octeon-3860-pip-interface";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>; /* interface */
+
+ ethernet@0 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x0>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ phy-handle = <&phy2>;
+ };
+ ethernet@1 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x1>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ phy-handle = <&phy3>;
+ };
+ ethernet@2 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x2>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ phy-handle = <&phy4>;
+ };
+ ethernet@3 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x3>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ phy-handle = <&phy5>;
+ };
+ };
+
+ interface@1 {
+ compatible = "cavium,octeon-3860-pip-interface";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>; /* interface */
+
+ ethernet@0 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x0>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ phy-handle = <&phy6>;
+ };
+ ethernet@1 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x1>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ phy-handle = <&phy7>;
+ };
+ ethernet@2 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x2>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ phy-handle = <&phy8>;
+ };
+ ethernet@3 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x3>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ phy-handle = <&phy9>;
+ };
+ };
+
+ interface@2 { /* DPI interface. */
+ compatible = "cavium,octeon-3860-pip-interface";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>; /* interface */
+
+ ethernet@0 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x0>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+ ethernet@1 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x1>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+ ethernet@2 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x2>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+ ethernet@3 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x3>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+ };
+
+ interface@3 { /* Loop interface. */
+ compatible = "cavium,octeon-3860-pip-interface";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>; /* interface */
+
+ ethernet@0 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x0>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+ ethernet@1 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x1>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+ ethernet@2 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x2>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+ ethernet@3 {
+ compatible = "cavium,octeon-3860-pip-port";
+ device_type = "network";
+ reg = <0x3>; /* Port */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+ };
+ };
+
+ twsi0: i2c@1180000001000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "cavium,octeon-3860-twsi";
+ reg = <0x11800 0x00001000 0x0 0x200>;
+ interrupt-parent = <&ciu>;
+ interrupts = <0 45 0>;
+ clock-rate = <100000>;
+
+ rtc@68 {
+ compatible = "dallas,ds1337";
+ reg = <0x68>;
+ };
+ tmp@4c {
+ compatible = "ti,tmp421";
+ reg = <0x4c>;
+ };
+ };
+
+ twsi1: i2c@1180000001200 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "cavium,octeon-3860-twsi";
+ reg = <0x11800 0x00001200 0x0 0x200>;
+ interrupt-parent = <&ciu>;
+ interrupts = <0 59 0>;
+ clock-rate = <100000>;
+ };
+ };
+
+ aliases {
+ mix0 = &mix0;
+ mix1 = &mix1;
+ pip = &pip;
+ smi0 = &smi0;
+ smi1 = &smi1;
+ twsi0 = &twsi0;
+ twsi1 = &twsi1;
+ };
+ };
diff --git a/arch/mips/cavium-octeon/octeon_68xx.dts b/arch/mips/cavium-octeon/octeon_68xx.dts
new file mode 100644
index 0000000..f2a8eab
--- /dev/null
+++ b/arch/mips/cavium-octeon/octeon_68xx.dts
@@ -0,0 +1,116 @@
+/dts-v1/;
+/*
+ * OCTEON 68XX device tree skeleton.
+ */
+/ {
+ model = "OCTEON";
+ compatible = "cavium,octeon-6880";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ soc@0 {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges; /* Direct mapping */
+
+ ciu2: interrupt-controller@1070100000000 {
+ compatible = "cavium,octeon-6880-ciu2";
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ reg = <0x10701 0x00000000 0x0 0x4000000>;
+ };
+
+ smi0: mdio@1180000003800 {
+ compatible = "cavium,octeon-3860-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x11800 0x00003800 0x0 0x40>;
+
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ device_type = "ethernet-phy";
+ };
+
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ device_type = "ethernet-phy";
+ };
+
+ phy3: ethernet-phy@3 {
+ reg = <3>;
+ device_type = "ethernet-phy";
+ };
+ };
+
+ smi1: mdio@1180000003880 {
+ compatible = "cavium,octeon-3860-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x11800 0x00003880 0x0 0x40>;
+ };
+
+ smi2: mdio@1180000003900 {
+ compatible = "cavium,octeon-3860-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x11800 0x00003900 0x0 0x40>;
+ };
+
+ smi3: mdio@1180000003980 {
+ compatible = "cavium,octeon-3860-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x11800 0x00003980 0x0 0x40>;
+ };
+
+ mix0: ethernet@1070000100000 {
+ compatible = "cavium,octeon-5750-mix";
+ device_type = "network";
+ reg = <0x10700 0x00100000 0x0 0x100>, /* MIX */
+ <0x11800 0xE0000000 0x0 0x300>, /* AGL */
+ <0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED */
+ <0x11800 0xE0002000 0x0 0x8>; /* AGL_PRT_CTL */
+ cell-index = <0>;
+ interrupt-parent = <&ciu2>;
+ interrupts = <0 62>, <1 46>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ phy-handle = <&phy0>;
+ };
+
+ twsi0: i2c@1180000001000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "cavium,octeon-3860-twsi";
+ reg = <0x11800 0x00001000 0x0 0x200>;
+ interrupt-parent = <&ciu2>;
+ interrupts = <0 45>;
+ clock-rate = <100000>;
+
+ rtc@68 {
+ compatible = "dallas,ds1337";
+ reg = <0x68>;
+ };
+ };
+
+ twsi1: i2c@1180000001200 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "cavium,octeon-3860-twsi";
+ reg = <0x11800 0x00001200 0x0 0x200>;
+ interrupt-parent = <&ciu2>;
+ interrupts = <0 59>;
+ clock-rate = <100000>;
+ };
+ };
+ aliases {
+ mix0 = &mix0;
+ smi0 = &smi0;
+ smi1 = &smi1;
+ smi2 = &smi2;
+ smi3 = &smi3;
+ twsi0 = &twsi0;
+ twsi1 = &twsi1;
+ };
+ };
--
1.7.2.3
^ permalink raw reply related [flat|nested] 40+ messages in thread[parent not found: <1299267744-17278-5-git-send-email-ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8@public.gmane.org>]
* Re: [RFC PATCH v2 04/12] MIPS: Octeon: Add device tree source files.
2011-03-04 19:42 ` David Daney
@ 2011-03-05 1:15 ` Grant Likely
-1 siblings, 0 replies; 40+ messages in thread
From: Grant Likely @ 2011-03-05 1:15 UTC (permalink / raw)
To: David Daney
Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, ralf-6z/3iImG2C8G8FEW9MqTrA
On Fri, Mar 04, 2011 at 11:42:16AM -0800, David Daney wrote:
> Signed-off-by: David Daney <ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8@public.gmane.org>
> ---
> arch/mips/cavium-octeon/.gitignore | 2 +
> arch/mips/cavium-octeon/Makefile | 13 ++
> arch/mips/cavium-octeon/octeon_3xxx.dts | 330 +++++++++++++++++++++++++++++++
> arch/mips/cavium-octeon/octeon_68xx.dts | 116 +++++++++++
> 4 files changed, 461 insertions(+), 0 deletions(-)
> create mode 100644 arch/mips/cavium-octeon/.gitignore
> create mode 100644 arch/mips/cavium-octeon/octeon_3xxx.dts
> create mode 100644 arch/mips/cavium-octeon/octeon_68xx.dts
>
> diff --git a/arch/mips/cavium-octeon/.gitignore b/arch/mips/cavium-octeon/.gitignore
> new file mode 100644
> index 0000000..39c9686
> --- /dev/null
> +++ b/arch/mips/cavium-octeon/.gitignore
> @@ -0,0 +1,2 @@
> +*.dtb.S
> +*.dtb
> diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile
> index 19eb043..5e25dce 100644
> --- a/arch/mips/cavium-octeon/Makefile
> +++ b/arch/mips/cavium-octeon/Makefile
> @@ -15,3 +15,16 @@ obj-y += octeon-memcpy.o
> obj-y += executive/
>
> obj-$(CONFIG_SMP) += smp.o
> +
> +DTS_FILES = octeon_3xxx.dts octeon_68xx.dts
> +DTB_FILES = $(patsubst %.dts, %.dtb, $(DTS_FILES))
> +
> +obj-y += $(patsubst %.dts, %.dtb.o, $(DTS_FILES))
> +
> +$(obj)/%.dtb: $(src)/%.dts
> + $(call cmd,dtc)
> +
> +# Let's keep the .dtb files around in case we want to look at them.
> +.SECONDARY: $(addprefix $(obj)/, $(DTB_FILES))
> +
> +clean-files += $(DTB_FILES) $(patsubst %.dtb, %.dtb.S, $(DTB_FILES))
> diff --git a/arch/mips/cavium-octeon/octeon_3xxx.dts b/arch/mips/cavium-octeon/octeon_3xxx.dts
> new file mode 100644
> index 0000000..6910d9d
> --- /dev/null
> +++ b/arch/mips/cavium-octeon/octeon_3xxx.dts
> @@ -0,0 +1,330 @@
> +/dts-v1/;
> +/*
> + * OCTEON 3XXX, 5XXX, 63XX device tree skeleton.
> + *
> + * This device tree is pruned and patched by early boot code before
> + * use. Because of this, it contains a super-set of the available
> + * devices and properties.
> + */
> +/ {
> + model = "OCTEON";
Be more specific in the model property. What is the full (human
readable) name of this board? Since your using this simply as a
template, it may be better to just omit this property entirely.
> + compatible = "cavium,octeon-3860";
All of the new compatible values in this file need to be documented in
Documentation/devicetree/bindings.
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
> + soc@0 {
> + compatible = "simple-bus";
> + #address-cells = <2>;
> + #size-cells = <2>;
> + ranges; /* Direct mapping */
> +
> + ciu: interrupt-controller@1070000000000 {
> + compatible = "cavium,octeon-3860-ciu";
> + interrupt-controller;
> + #address-cells = <0>;
> + /* Interrupts are specified by three parts:
> + * 1) Controller register (0 or 1)
> + * 2) Bit within the register (0..63)
> + * 3) Triggering (0 - level active high
> + * 1 - level active low
> + * 2 - edge rising
> + * 3 - edge falling
> + *
> + * For non-GPIO sources, the triggering cannot be
> + * changed and is ignored.
> + */
> + #interrupt-cells = <3>;
> + reg = <0x10700 0x00000000 0x0 0x7000>;
> + };
> +
> + smi0: mdio@1180000001800 {
> + compatible = "cavium,octeon-3860-mdio";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0x11800 0x00001800 0x0 0x40>;
> +
> + phy0: ethernet-phy@0 {
> + reg = <0>;
Should have a compatible property for each of the phys
> + };
> +
> + phy1: ethernet-phy@1 {
> + reg = <1>;
> + };
> +
> + phy2: ethernet-phy@2 {
> + reg = <2>;
> + marvell,reg-init = <3 0x10 0 0x5777>,
> + <3 0x11 0 0x00aa>,
> + <3 0x12 0 0x4105>,
> + <3 0x13 0 0x0a60>;
> + };
> + phy3: ethernet-phy@3 {
> + reg = <3>;
> + marvell,reg-init = <3 0x10 0 0x5777>,
> + <3 0x11 0 0x00aa>,
> + <3 0x12 0 0x4105>,
> + <3 0x13 0 0x0a60>;
> + };
> + phy4: ethernet-phy@4 {
> + reg = <4>;
> + marvell,reg-init = <3 0x10 0 0x5777>,
> + <3 0x11 0 0x00aa>,
> + <3 0x12 0 0x4105>,
> + <3 0x13 0 0x0a60>;
> + };
> + phy5: ethernet-phy@5 {
> + reg = <5>;
> + marvell,reg-init = <3 0x10 0 0x5777>,
> + <3 0x11 0 0x00aa>,
> + <3 0x12 0 0x4105>,
> + <3 0x13 0 0x0a60>;
> + };
> +
> + phy6: ethernet-phy@6 {
> + reg = <6>;
> + marvell,reg-init = <3 0x10 0 0x5777>,
> + <3 0x11 0 0x00aa>,
> + <3 0x12 0 0x4105>,
> + <3 0x13 0 0x0a60>;
> + };
> + phy7: ethernet-phy@7 {
> + reg = <7>;
> + marvell,reg-init = <3 0x10 0 0x5777>,
> + <3 0x11 0 0x00aa>,
> + <3 0x12 0 0x4105>,
> + <3 0x13 0 0x0a60>;
> + };
> + phy8: ethernet-phy@8 {
> + reg = <8>;
> + marvell,reg-init = <3 0x10 0 0x5777>,
> + <3 0x11 0 0x00aa>,
> + <3 0x12 0 0x4105>,
> + <3 0x13 0 0x0a60>;
> + };
> + phy9: ethernet-phy@9 {
> + reg = <9>;
> + marvell,reg-init = <3 0x10 0 0x5777>,
> + <3 0x11 0 0x00aa>,
> + <3 0x12 0 0x4105>,
> + <3 0x13 0 0x0a60>;
> + };
> + };
> +
> + smi1: mdio@1180000001900 {
> + compatible = "cavium,octeon-3860-mdio";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0x11800 0x00001900 0x0 0x40>;
> + };
> +
> + mix0: ethernet@1070000100000 {
> + compatible = "cavium,octeon-5750-mix";
> + device_type = "network";
Drop 'device_type' property. It only makes sense if you have a real
OpenFirmware implementation. Ditto through the rest of the file.
> + reg = <0x10700 0x00100000 0x0 0x100>, /* MIX */
> + <0x11800 0xE0000000 0x0 0x300>, /* AGL */
> + <0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED */
> + <0x11800 0xE0002000 0x0 0x8>; /* AGL_PRT_CTL */
> + cell-index = <0>;
> + interrupt-parent = <&ciu>;
If you put this property up in the root node, then you can omit it
from everywhere else because they'll pick it up as the default
interrupt controller.
> + interrupts = <0 62 0>, <1 46 0>;
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + phy-handle = <&phy0>;
> + };
> +
> + mix1: ethernet@1070000100800 {
> + compatible = "cavium,octeon-5750-mix";
> + device_type = "network";
> + reg = <0x10700 0x00100800 0x0 0x100>, /* MIX */
> + <0x11800 0xE0000800 0x0 0x300>, /* AGL */
> + <0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED */
> + <0x11800 0xE0002008 0x0 0x8>; /* AGL_PRT_CTL */
> + cell-index = <1>;
> + interrupt-parent = <&ciu>;
> + interrupts = <1 18 0>, < 1 46 0>;
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + phy-handle = <&phy1>;
> + };
> +
> + pip: pip@11800a0000000 {
> + compatible = "cavium,octeon-3860-pip";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0x11800 0xa0000000 0x0 0x2000>;
> +
> + interface@0 {
> + compatible = "cavium,octeon-3860-pip-interface";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0>; /* interface */
> +
> + ethernet@0 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x0>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + phy-handle = <&phy2>;
> + };
> + ethernet@1 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x1>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + phy-handle = <&phy3>;
> + };
> + ethernet@2 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x2>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + phy-handle = <&phy4>;
> + };
> + ethernet@3 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x3>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + phy-handle = <&phy5>;
> + };
> + };
> +
> + interface@1 {
> + compatible = "cavium,octeon-3860-pip-interface";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <1>; /* interface */
> +
> + ethernet@0 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x0>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + phy-handle = <&phy6>;
> + };
> + ethernet@1 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x1>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + phy-handle = <&phy7>;
> + };
> + ethernet@2 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x2>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + phy-handle = <&phy8>;
> + };
> + ethernet@3 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x3>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + phy-handle = <&phy9>;
> + };
> + };
> +
> + interface@2 { /* DPI interface. */
> + compatible = "cavium,octeon-3860-pip-interface";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <2>; /* interface */
> +
> + ethernet@0 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x0>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + };
> + ethernet@1 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x1>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + };
> + ethernet@2 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x2>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + };
> + ethernet@3 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x3>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + };
> + };
> +
> + interface@3 { /* Loop interface. */
> + compatible = "cavium,octeon-3860-pip-interface";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <3>; /* interface */
> +
> + ethernet@0 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x0>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + };
> + ethernet@1 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x1>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + };
> + ethernet@2 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x2>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + };
> + ethernet@3 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x3>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + };
> + };
> + };
> +
> + twsi0: i2c@1180000001000 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + compatible = "cavium,octeon-3860-twsi";
> + reg = <0x11800 0x00001000 0x0 0x200>;
> + interrupt-parent = <&ciu>;
> + interrupts = <0 45 0>;
> + clock-rate = <100000>;
> +
> + rtc@68 {
> + compatible = "dallas,ds1337";
> + reg = <0x68>;
> + };
> + tmp@4c {
> + compatible = "ti,tmp421";
> + reg = <0x4c>;
> + };
> + };
> +
> + twsi1: i2c@1180000001200 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + compatible = "cavium,octeon-3860-twsi";
> + reg = <0x11800 0x00001200 0x0 0x200>;
> + interrupt-parent = <&ciu>;
> + interrupts = <0 59 0>;
> + clock-rate = <100000>;
> + };
> + };
> +
> + aliases {
> + mix0 = &mix0;
> + mix1 = &mix1;
> + pip = &pip;
> + smi0 = &smi0;
> + smi1 = &smi1;
> + twsi0 = &twsi0;
> + twsi1 = &twsi1;
> + };
> + };
> diff --git a/arch/mips/cavium-octeon/octeon_68xx.dts b/arch/mips/cavium-octeon/octeon_68xx.dts
> new file mode 100644
> index 0000000..f2a8eab
> --- /dev/null
> +++ b/arch/mips/cavium-octeon/octeon_68xx.dts
> @@ -0,0 +1,116 @@
> +/dts-v1/;
> +/*
> + * OCTEON 68XX device tree skeleton.
> + */
> +/ {
> + model = "OCTEON";
> + compatible = "cavium,octeon-6880";
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
> + soc@0 {
> + compatible = "simple-bus";
> + #address-cells = <2>;
> + #size-cells = <2>;
> + ranges; /* Direct mapping */
> +
> + ciu2: interrupt-controller@1070100000000 {
> + compatible = "cavium,octeon-6880-ciu2";
> + interrupt-controller;
> + #address-cells = <0>;
> + #interrupt-cells = <2>;
> + reg = <0x10701 0x00000000 0x0 0x4000000>;
> + };
> +
> + smi0: mdio@1180000003800 {
> + compatible = "cavium,octeon-3860-mdio";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0x11800 0x00003800 0x0 0x40>;
> +
> + phy0: ethernet-phy@0 {
> + reg = <0>;
> + device_type = "ethernet-phy";
> + };
> +
> + phy1: ethernet-phy@1 {
> + reg = <1>;
> + device_type = "ethernet-phy";
> + };
> +
> + phy3: ethernet-phy@3 {
> + reg = <3>;
> + device_type = "ethernet-phy";
> + };
> + };
> +
> + smi1: mdio@1180000003880 {
> + compatible = "cavium,octeon-3860-mdio";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0x11800 0x00003880 0x0 0x40>;
> + };
> +
> + smi2: mdio@1180000003900 {
> + compatible = "cavium,octeon-3860-mdio";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0x11800 0x00003900 0x0 0x40>;
> + };
> +
> + smi3: mdio@1180000003980 {
> + compatible = "cavium,octeon-3860-mdio";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0x11800 0x00003980 0x0 0x40>;
> + };
> +
> + mix0: ethernet@1070000100000 {
> + compatible = "cavium,octeon-5750-mix";
> + device_type = "network";
> + reg = <0x10700 0x00100000 0x0 0x100>, /* MIX */
> + <0x11800 0xE0000000 0x0 0x300>, /* AGL */
> + <0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED */
> + <0x11800 0xE0002000 0x0 0x8>; /* AGL_PRT_CTL */
> + cell-index = <0>;
> + interrupt-parent = <&ciu2>;
> + interrupts = <0 62>, <1 46>;
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + phy-handle = <&phy0>;
> + };
> +
> + twsi0: i2c@1180000001000 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + compatible = "cavium,octeon-3860-twsi";
> + reg = <0x11800 0x00001000 0x0 0x200>;
> + interrupt-parent = <&ciu2>;
> + interrupts = <0 45>;
> + clock-rate = <100000>;
> +
> + rtc@68 {
> + compatible = "dallas,ds1337";
> + reg = <0x68>;
> + };
> + };
> +
> + twsi1: i2c@1180000001200 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + compatible = "cavium,octeon-3860-twsi";
> + reg = <0x11800 0x00001200 0x0 0x200>;
> + interrupt-parent = <&ciu2>;
> + interrupts = <0 59>;
> + clock-rate = <100000>;
> + };
> + };
> + aliases {
> + mix0 = &mix0;
> + smi0 = &smi0;
> + smi1 = &smi1;
> + smi2 = &smi2;
> + smi3 = &smi3;
> + twsi0 = &twsi0;
> + twsi1 = &twsi1;
> + };
> + };
> --
> 1.7.2.3
>
^ permalink raw reply [flat|nested] 40+ messages in thread* Re: [RFC PATCH v2 04/12] MIPS: Octeon: Add device tree source files.
@ 2011-03-05 1:15 ` Grant Likely
0 siblings, 0 replies; 40+ messages in thread
From: Grant Likely @ 2011-03-05 1:15 UTC (permalink / raw)
To: David Daney; +Cc: linux-mips, ralf, devicetree-discuss, linux-kernel
On Fri, Mar 04, 2011 at 11:42:16AM -0800, David Daney wrote:
> Signed-off-by: David Daney <ddaney@caviumnetworks.com>
> ---
> arch/mips/cavium-octeon/.gitignore | 2 +
> arch/mips/cavium-octeon/Makefile | 13 ++
> arch/mips/cavium-octeon/octeon_3xxx.dts | 330 +++++++++++++++++++++++++++++++
> arch/mips/cavium-octeon/octeon_68xx.dts | 116 +++++++++++
> 4 files changed, 461 insertions(+), 0 deletions(-)
> create mode 100644 arch/mips/cavium-octeon/.gitignore
> create mode 100644 arch/mips/cavium-octeon/octeon_3xxx.dts
> create mode 100644 arch/mips/cavium-octeon/octeon_68xx.dts
>
> diff --git a/arch/mips/cavium-octeon/.gitignore b/arch/mips/cavium-octeon/.gitignore
> new file mode 100644
> index 0000000..39c9686
> --- /dev/null
> +++ b/arch/mips/cavium-octeon/.gitignore
> @@ -0,0 +1,2 @@
> +*.dtb.S
> +*.dtb
> diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile
> index 19eb043..5e25dce 100644
> --- a/arch/mips/cavium-octeon/Makefile
> +++ b/arch/mips/cavium-octeon/Makefile
> @@ -15,3 +15,16 @@ obj-y += octeon-memcpy.o
> obj-y += executive/
>
> obj-$(CONFIG_SMP) += smp.o
> +
> +DTS_FILES = octeon_3xxx.dts octeon_68xx.dts
> +DTB_FILES = $(patsubst %.dts, %.dtb, $(DTS_FILES))
> +
> +obj-y += $(patsubst %.dts, %.dtb.o, $(DTS_FILES))
> +
> +$(obj)/%.dtb: $(src)/%.dts
> + $(call cmd,dtc)
> +
> +# Let's keep the .dtb files around in case we want to look at them.
> +.SECONDARY: $(addprefix $(obj)/, $(DTB_FILES))
> +
> +clean-files += $(DTB_FILES) $(patsubst %.dtb, %.dtb.S, $(DTB_FILES))
> diff --git a/arch/mips/cavium-octeon/octeon_3xxx.dts b/arch/mips/cavium-octeon/octeon_3xxx.dts
> new file mode 100644
> index 0000000..6910d9d
> --- /dev/null
> +++ b/arch/mips/cavium-octeon/octeon_3xxx.dts
> @@ -0,0 +1,330 @@
> +/dts-v1/;
> +/*
> + * OCTEON 3XXX, 5XXX, 63XX device tree skeleton.
> + *
> + * This device tree is pruned and patched by early boot code before
> + * use. Because of this, it contains a super-set of the available
> + * devices and properties.
> + */
> +/ {
> + model = "OCTEON";
Be more specific in the model property. What is the full (human
readable) name of this board? Since your using this simply as a
template, it may be better to just omit this property entirely.
> + compatible = "cavium,octeon-3860";
All of the new compatible values in this file need to be documented in
Documentation/devicetree/bindings.
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
> + soc@0 {
> + compatible = "simple-bus";
> + #address-cells = <2>;
> + #size-cells = <2>;
> + ranges; /* Direct mapping */
> +
> + ciu: interrupt-controller@1070000000000 {
> + compatible = "cavium,octeon-3860-ciu";
> + interrupt-controller;
> + #address-cells = <0>;
> + /* Interrupts are specified by three parts:
> + * 1) Controller register (0 or 1)
> + * 2) Bit within the register (0..63)
> + * 3) Triggering (0 - level active high
> + * 1 - level active low
> + * 2 - edge rising
> + * 3 - edge falling
> + *
> + * For non-GPIO sources, the triggering cannot be
> + * changed and is ignored.
> + */
> + #interrupt-cells = <3>;
> + reg = <0x10700 0x00000000 0x0 0x7000>;
> + };
> +
> + smi0: mdio@1180000001800 {
> + compatible = "cavium,octeon-3860-mdio";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0x11800 0x00001800 0x0 0x40>;
> +
> + phy0: ethernet-phy@0 {
> + reg = <0>;
Should have a compatible property for each of the phys
> + };
> +
> + phy1: ethernet-phy@1 {
> + reg = <1>;
> + };
> +
> + phy2: ethernet-phy@2 {
> + reg = <2>;
> + marvell,reg-init = <3 0x10 0 0x5777>,
> + <3 0x11 0 0x00aa>,
> + <3 0x12 0 0x4105>,
> + <3 0x13 0 0x0a60>;
> + };
> + phy3: ethernet-phy@3 {
> + reg = <3>;
> + marvell,reg-init = <3 0x10 0 0x5777>,
> + <3 0x11 0 0x00aa>,
> + <3 0x12 0 0x4105>,
> + <3 0x13 0 0x0a60>;
> + };
> + phy4: ethernet-phy@4 {
> + reg = <4>;
> + marvell,reg-init = <3 0x10 0 0x5777>,
> + <3 0x11 0 0x00aa>,
> + <3 0x12 0 0x4105>,
> + <3 0x13 0 0x0a60>;
> + };
> + phy5: ethernet-phy@5 {
> + reg = <5>;
> + marvell,reg-init = <3 0x10 0 0x5777>,
> + <3 0x11 0 0x00aa>,
> + <3 0x12 0 0x4105>,
> + <3 0x13 0 0x0a60>;
> + };
> +
> + phy6: ethernet-phy@6 {
> + reg = <6>;
> + marvell,reg-init = <3 0x10 0 0x5777>,
> + <3 0x11 0 0x00aa>,
> + <3 0x12 0 0x4105>,
> + <3 0x13 0 0x0a60>;
> + };
> + phy7: ethernet-phy@7 {
> + reg = <7>;
> + marvell,reg-init = <3 0x10 0 0x5777>,
> + <3 0x11 0 0x00aa>,
> + <3 0x12 0 0x4105>,
> + <3 0x13 0 0x0a60>;
> + };
> + phy8: ethernet-phy@8 {
> + reg = <8>;
> + marvell,reg-init = <3 0x10 0 0x5777>,
> + <3 0x11 0 0x00aa>,
> + <3 0x12 0 0x4105>,
> + <3 0x13 0 0x0a60>;
> + };
> + phy9: ethernet-phy@9 {
> + reg = <9>;
> + marvell,reg-init = <3 0x10 0 0x5777>,
> + <3 0x11 0 0x00aa>,
> + <3 0x12 0 0x4105>,
> + <3 0x13 0 0x0a60>;
> + };
> + };
> +
> + smi1: mdio@1180000001900 {
> + compatible = "cavium,octeon-3860-mdio";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0x11800 0x00001900 0x0 0x40>;
> + };
> +
> + mix0: ethernet@1070000100000 {
> + compatible = "cavium,octeon-5750-mix";
> + device_type = "network";
Drop 'device_type' property. It only makes sense if you have a real
OpenFirmware implementation. Ditto through the rest of the file.
> + reg = <0x10700 0x00100000 0x0 0x100>, /* MIX */
> + <0x11800 0xE0000000 0x0 0x300>, /* AGL */
> + <0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED */
> + <0x11800 0xE0002000 0x0 0x8>; /* AGL_PRT_CTL */
> + cell-index = <0>;
> + interrupt-parent = <&ciu>;
If you put this property up in the root node, then you can omit it
from everywhere else because they'll pick it up as the default
interrupt controller.
> + interrupts = <0 62 0>, <1 46 0>;
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + phy-handle = <&phy0>;
> + };
> +
> + mix1: ethernet@1070000100800 {
> + compatible = "cavium,octeon-5750-mix";
> + device_type = "network";
> + reg = <0x10700 0x00100800 0x0 0x100>, /* MIX */
> + <0x11800 0xE0000800 0x0 0x300>, /* AGL */
> + <0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED */
> + <0x11800 0xE0002008 0x0 0x8>; /* AGL_PRT_CTL */
> + cell-index = <1>;
> + interrupt-parent = <&ciu>;
> + interrupts = <1 18 0>, < 1 46 0>;
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + phy-handle = <&phy1>;
> + };
> +
> + pip: pip@11800a0000000 {
> + compatible = "cavium,octeon-3860-pip";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0x11800 0xa0000000 0x0 0x2000>;
> +
> + interface@0 {
> + compatible = "cavium,octeon-3860-pip-interface";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0>; /* interface */
> +
> + ethernet@0 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x0>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + phy-handle = <&phy2>;
> + };
> + ethernet@1 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x1>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + phy-handle = <&phy3>;
> + };
> + ethernet@2 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x2>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + phy-handle = <&phy4>;
> + };
> + ethernet@3 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x3>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + phy-handle = <&phy5>;
> + };
> + };
> +
> + interface@1 {
> + compatible = "cavium,octeon-3860-pip-interface";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <1>; /* interface */
> +
> + ethernet@0 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x0>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + phy-handle = <&phy6>;
> + };
> + ethernet@1 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x1>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + phy-handle = <&phy7>;
> + };
> + ethernet@2 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x2>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + phy-handle = <&phy8>;
> + };
> + ethernet@3 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x3>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + phy-handle = <&phy9>;
> + };
> + };
> +
> + interface@2 { /* DPI interface. */
> + compatible = "cavium,octeon-3860-pip-interface";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <2>; /* interface */
> +
> + ethernet@0 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x0>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + };
> + ethernet@1 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x1>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + };
> + ethernet@2 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x2>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + };
> + ethernet@3 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x3>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + };
> + };
> +
> + interface@3 { /* Loop interface. */
> + compatible = "cavium,octeon-3860-pip-interface";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <3>; /* interface */
> +
> + ethernet@0 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x0>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + };
> + ethernet@1 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x1>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + };
> + ethernet@2 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x2>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + };
> + ethernet@3 {
> + compatible = "cavium,octeon-3860-pip-port";
> + device_type = "network";
> + reg = <0x3>; /* Port */
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + };
> + };
> + };
> +
> + twsi0: i2c@1180000001000 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + compatible = "cavium,octeon-3860-twsi";
> + reg = <0x11800 0x00001000 0x0 0x200>;
> + interrupt-parent = <&ciu>;
> + interrupts = <0 45 0>;
> + clock-rate = <100000>;
> +
> + rtc@68 {
> + compatible = "dallas,ds1337";
> + reg = <0x68>;
> + };
> + tmp@4c {
> + compatible = "ti,tmp421";
> + reg = <0x4c>;
> + };
> + };
> +
> + twsi1: i2c@1180000001200 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + compatible = "cavium,octeon-3860-twsi";
> + reg = <0x11800 0x00001200 0x0 0x200>;
> + interrupt-parent = <&ciu>;
> + interrupts = <0 59 0>;
> + clock-rate = <100000>;
> + };
> + };
> +
> + aliases {
> + mix0 = &mix0;
> + mix1 = &mix1;
> + pip = &pip;
> + smi0 = &smi0;
> + smi1 = &smi1;
> + twsi0 = &twsi0;
> + twsi1 = &twsi1;
> + };
> + };
> diff --git a/arch/mips/cavium-octeon/octeon_68xx.dts b/arch/mips/cavium-octeon/octeon_68xx.dts
> new file mode 100644
> index 0000000..f2a8eab
> --- /dev/null
> +++ b/arch/mips/cavium-octeon/octeon_68xx.dts
> @@ -0,0 +1,116 @@
> +/dts-v1/;
> +/*
> + * OCTEON 68XX device tree skeleton.
> + */
> +/ {
> + model = "OCTEON";
> + compatible = "cavium,octeon-6880";
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
> + soc@0 {
> + compatible = "simple-bus";
> + #address-cells = <2>;
> + #size-cells = <2>;
> + ranges; /* Direct mapping */
> +
> + ciu2: interrupt-controller@1070100000000 {
> + compatible = "cavium,octeon-6880-ciu2";
> + interrupt-controller;
> + #address-cells = <0>;
> + #interrupt-cells = <2>;
> + reg = <0x10701 0x00000000 0x0 0x4000000>;
> + };
> +
> + smi0: mdio@1180000003800 {
> + compatible = "cavium,octeon-3860-mdio";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0x11800 0x00003800 0x0 0x40>;
> +
> + phy0: ethernet-phy@0 {
> + reg = <0>;
> + device_type = "ethernet-phy";
> + };
> +
> + phy1: ethernet-phy@1 {
> + reg = <1>;
> + device_type = "ethernet-phy";
> + };
> +
> + phy3: ethernet-phy@3 {
> + reg = <3>;
> + device_type = "ethernet-phy";
> + };
> + };
> +
> + smi1: mdio@1180000003880 {
> + compatible = "cavium,octeon-3860-mdio";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0x11800 0x00003880 0x0 0x40>;
> + };
> +
> + smi2: mdio@1180000003900 {
> + compatible = "cavium,octeon-3860-mdio";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0x11800 0x00003900 0x0 0x40>;
> + };
> +
> + smi3: mdio@1180000003980 {
> + compatible = "cavium,octeon-3860-mdio";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0x11800 0x00003980 0x0 0x40>;
> + };
> +
> + mix0: ethernet@1070000100000 {
> + compatible = "cavium,octeon-5750-mix";
> + device_type = "network";
> + reg = <0x10700 0x00100000 0x0 0x100>, /* MIX */
> + <0x11800 0xE0000000 0x0 0x300>, /* AGL */
> + <0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED */
> + <0x11800 0xE0002000 0x0 0x8>; /* AGL_PRT_CTL */
> + cell-index = <0>;
> + interrupt-parent = <&ciu2>;
> + interrupts = <0 62>, <1 46>;
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + phy-handle = <&phy0>;
> + };
> +
> + twsi0: i2c@1180000001000 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + compatible = "cavium,octeon-3860-twsi";
> + reg = <0x11800 0x00001000 0x0 0x200>;
> + interrupt-parent = <&ciu2>;
> + interrupts = <0 45>;
> + clock-rate = <100000>;
> +
> + rtc@68 {
> + compatible = "dallas,ds1337";
> + reg = <0x68>;
> + };
> + };
> +
> + twsi1: i2c@1180000001200 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + compatible = "cavium,octeon-3860-twsi";
> + reg = <0x11800 0x00001200 0x0 0x200>;
> + interrupt-parent = <&ciu2>;
> + interrupts = <0 59>;
> + clock-rate = <100000>;
> + };
> + };
> + aliases {
> + mix0 = &mix0;
> + smi0 = &smi0;
> + smi1 = &smi1;
> + smi2 = &smi2;
> + smi3 = &smi3;
> + twsi0 = &twsi0;
> + twsi1 = &twsi1;
> + };
> + };
> --
> 1.7.2.3
>
^ permalink raw reply [flat|nested] 40+ messages in thread
* [RFC PATCH v2 05/12] MIPS: Prune some target specific code out of prom.c
2011-03-04 19:42 ` David Daney
@ 2011-03-04 19:42 ` David Daney
-1 siblings, 0 replies; 40+ messages in thread
From: David Daney @ 2011-03-04 19:42 UTC (permalink / raw)
To: linux-mips-6z/3iImG2C8G8FEW9MqTrA, ralf-6z/3iImG2C8G8FEW9MqTrA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
grant.likely-s3s/WqlpOiPyB63q8FvJNQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: David Daney
This code is not common enough to be in a shared file. It is also not
used by any existing boards, so just remove it.
Signed-off-by: David Daney <ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8@public.gmane.org>
---
arch/mips/kernel/prom.c | 49 -----------------------------------------------
1 files changed, 0 insertions(+), 49 deletions(-)
diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c
index a19811e9..a07b6f1 100644
--- a/arch/mips/kernel/prom.c
+++ b/arch/mips/kernel/prom.c
@@ -59,52 +59,3 @@ void __init early_init_dt_setup_initrd_arch(unsigned long start,
initrd_below_start_ok = 1;
}
#endif
-
-/*
- * irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq#
- *
- * Currently the mapping mechanism is trivial; simple flat hwirq numbers are
- * mapped 1:1 onto Linux irq numbers. Cascaded irq controllers are not
- * supported.
- */
-unsigned int irq_create_of_mapping(struct device_node *controller,
- const u32 *intspec, unsigned int intsize)
-{
- return intspec[0];
-}
-EXPORT_SYMBOL_GPL(irq_create_of_mapping);
-
-void __init early_init_devtree(void *params)
-{
- /* Setup flat device-tree pointer */
- initial_boot_params = params;
-
- /* Retrieve various informations from the /chosen node of the
- * device-tree, including the platform type, initrd location and
- * size, and more ...
- */
- of_scan_flat_dt(early_init_dt_scan_chosen, NULL);
-
- /* Scan memory nodes */
- of_scan_flat_dt(early_init_dt_scan_root, NULL);
- of_scan_flat_dt(early_init_dt_scan_memory_arch, NULL);
-}
-
-void __init device_tree_init(void)
-{
- unsigned long base, size;
-
- if (!initial_boot_params)
- return;
-
- base = virt_to_phys((void *)initial_boot_params);
- size = be32_to_cpu(initial_boot_params->totalsize);
-
- /* Before we do anything, lets reserve the dt blob */
- reserve_mem_mach(base, size);
-
- unflatten_device_tree();
-
- /* free the space reserved for the dt blob */
- free_mem_mach(base, size);
-}
--
1.7.2.3
^ permalink raw reply related [flat|nested] 40+ messages in thread* [RFC PATCH v2 05/12] MIPS: Prune some target specific code out of prom.c
@ 2011-03-04 19:42 ` David Daney
0 siblings, 0 replies; 40+ messages in thread
From: David Daney @ 2011-03-04 19:42 UTC (permalink / raw)
To: linux-mips, ralf, devicetree-discuss, grant.likely, linux-kernel
Cc: David Daney
This code is not common enough to be in a shared file. It is also not
used by any existing boards, so just remove it.
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
---
arch/mips/kernel/prom.c | 49 -----------------------------------------------
1 files changed, 0 insertions(+), 49 deletions(-)
diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c
index a19811e9..a07b6f1 100644
--- a/arch/mips/kernel/prom.c
+++ b/arch/mips/kernel/prom.c
@@ -59,52 +59,3 @@ void __init early_init_dt_setup_initrd_arch(unsigned long start,
initrd_below_start_ok = 1;
}
#endif
-
-/*
- * irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq#
- *
- * Currently the mapping mechanism is trivial; simple flat hwirq numbers are
- * mapped 1:1 onto Linux irq numbers. Cascaded irq controllers are not
- * supported.
- */
-unsigned int irq_create_of_mapping(struct device_node *controller,
- const u32 *intspec, unsigned int intsize)
-{
- return intspec[0];
-}
-EXPORT_SYMBOL_GPL(irq_create_of_mapping);
-
-void __init early_init_devtree(void *params)
-{
- /* Setup flat device-tree pointer */
- initial_boot_params = params;
-
- /* Retrieve various informations from the /chosen node of the
- * device-tree, including the platform type, initrd location and
- * size, and more ...
- */
- of_scan_flat_dt(early_init_dt_scan_chosen, NULL);
-
- /* Scan memory nodes */
- of_scan_flat_dt(early_init_dt_scan_root, NULL);
- of_scan_flat_dt(early_init_dt_scan_memory_arch, NULL);
-}
-
-void __init device_tree_init(void)
-{
- unsigned long base, size;
-
- if (!initial_boot_params)
- return;
-
- base = virt_to_phys((void *)initial_boot_params);
- size = be32_to_cpu(initial_boot_params->totalsize);
-
- /* Before we do anything, lets reserve the dt blob */
- reserve_mem_mach(base, size);
-
- unflatten_device_tree();
-
- /* free the space reserved for the dt blob */
- free_mem_mach(base, size);
-}
--
1.7.2.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [RFC PATCH v2 06/12] MIPS: Octeon: Add a irq_create_of_mapping() implementation.
2011-03-04 19:42 ` David Daney
@ 2011-03-04 19:42 ` David Daney
-1 siblings, 0 replies; 40+ messages in thread
From: David Daney @ 2011-03-04 19:42 UTC (permalink / raw)
To: linux-mips-6z/3iImG2C8G8FEW9MqTrA, ralf-6z/3iImG2C8G8FEW9MqTrA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
grant.likely-s3s/WqlpOiPyB63q8FvJNQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: David Daney
This is needed for Octeon to use the Device Tree.
Signed-off-by: David Daney <ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8@public.gmane.org>
---
arch/mips/cavium-octeon/octeon-irq.c | 25 +++++++++++++++++++++++++
1 files changed, 25 insertions(+), 0 deletions(-)
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
index b365710..b0a9261 100644
--- a/arch/mips/cavium-octeon/octeon-irq.c
+++ b/arch/mips/cavium-octeon/octeon-irq.c
@@ -8,7 +8,9 @@
#include <linux/interrupt.h>
#include <linux/bitops.h>
+#include <linux/module.h>
#include <linux/percpu.h>
+#include <linux/of_irq.h>
#include <linux/irq.h>
#include <linux/smp.h>
@@ -64,6 +66,29 @@ static void __init octeon_irq_set_ciu_mapping(int irq, int line, int bit,
octeon_irq_ciu_to_irq[line][bit] = irq;
}
+/*
+ * irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq#
+ *
+ * Octeon irq maps are a pair of indexes. The first selects either
+ * ciu0 or ciu1, the second is the bit within the ciu register.
+ */
+unsigned int irq_create_of_mapping(struct device_node *controller,
+ const u32 *intspec, unsigned int intsize)
+{
+ int ciu, bit;
+ unsigned int irq = 0;
+
+ ciu = be32_to_cpup(intspec);
+ bit = be32_to_cpup(intspec + 1);
+
+ if (ciu < 8 && bit < 64)
+ irq = octeon_irq_ciu_to_irq[ciu][bit];
+
+ return irq;
+}
+EXPORT_SYMBOL_GPL(irq_create_of_mapping);
+
+
static int octeon_coreid_for_cpu(int cpu)
{
#ifdef CONFIG_SMP
--
1.7.2.3
^ permalink raw reply related [flat|nested] 40+ messages in thread* [RFC PATCH v2 06/12] MIPS: Octeon: Add a irq_create_of_mapping() implementation.
@ 2011-03-04 19:42 ` David Daney
0 siblings, 0 replies; 40+ messages in thread
From: David Daney @ 2011-03-04 19:42 UTC (permalink / raw)
To: linux-mips, ralf, devicetree-discuss, grant.likely, linux-kernel
Cc: David Daney
This is needed for Octeon to use the Device Tree.
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
---
arch/mips/cavium-octeon/octeon-irq.c | 25 +++++++++++++++++++++++++
1 files changed, 25 insertions(+), 0 deletions(-)
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
index b365710..b0a9261 100644
--- a/arch/mips/cavium-octeon/octeon-irq.c
+++ b/arch/mips/cavium-octeon/octeon-irq.c
@@ -8,7 +8,9 @@
#include <linux/interrupt.h>
#include <linux/bitops.h>
+#include <linux/module.h>
#include <linux/percpu.h>
+#include <linux/of_irq.h>
#include <linux/irq.h>
#include <linux/smp.h>
@@ -64,6 +66,29 @@ static void __init octeon_irq_set_ciu_mapping(int irq, int line, int bit,
octeon_irq_ciu_to_irq[line][bit] = irq;
}
+/*
+ * irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq#
+ *
+ * Octeon irq maps are a pair of indexes. The first selects either
+ * ciu0 or ciu1, the second is the bit within the ciu register.
+ */
+unsigned int irq_create_of_mapping(struct device_node *controller,
+ const u32 *intspec, unsigned int intsize)
+{
+ int ciu, bit;
+ unsigned int irq = 0;
+
+ ciu = be32_to_cpup(intspec);
+ bit = be32_to_cpup(intspec + 1);
+
+ if (ciu < 8 && bit < 64)
+ irq = octeon_irq_ciu_to_irq[ciu][bit];
+
+ return irq;
+}
+EXPORT_SYMBOL_GPL(irq_create_of_mapping);
+
+
static int octeon_coreid_for_cpu(int cpu)
{
#ifdef CONFIG_SMP
--
1.7.2.3
^ permalink raw reply related [flat|nested] 40+ messages in thread* Re: [RFC PATCH v2 06/12] MIPS: Octeon: Add a irq_create_of_mapping() implementation.
2011-03-04 19:42 ` David Daney
(?)
@ 2011-03-05 1:07 ` Grant Likely
2011-03-11 18:27 ` David Daney
-1 siblings, 1 reply; 40+ messages in thread
From: Grant Likely @ 2011-03-05 1:07 UTC (permalink / raw)
To: David Daney; +Cc: linux-mips, ralf, devicetree-discuss, linux-kernel
On Fri, Mar 04, 2011 at 11:42:18AM -0800, David Daney wrote:
> This is needed for Octeon to use the Device Tree.
>
> Signed-off-by: David Daney <ddaney@caviumnetworks.com>
> ---
> arch/mips/cavium-octeon/octeon-irq.c | 25 +++++++++++++++++++++++++
> 1 files changed, 25 insertions(+), 0 deletions(-)
>
> diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
> index b365710..b0a9261 100644
> --- a/arch/mips/cavium-octeon/octeon-irq.c
> +++ b/arch/mips/cavium-octeon/octeon-irq.c
> @@ -8,7 +8,9 @@
>
> #include <linux/interrupt.h>
> #include <linux/bitops.h>
> +#include <linux/module.h>
> #include <linux/percpu.h>
> +#include <linux/of_irq.h>
> #include <linux/irq.h>
> #include <linux/smp.h>
>
> @@ -64,6 +66,29 @@ static void __init octeon_irq_set_ciu_mapping(int irq, int line, int bit,
> octeon_irq_ciu_to_irq[line][bit] = irq;
> }
>
> +/*
> + * irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq#
> + *
> + * Octeon irq maps are a pair of indexes. The first selects either
> + * ciu0 or ciu1, the second is the bit within the ciu register.
> + */
Is each 'ciu' an interrupt controller, or a 'bank' within the
controller? Also, it is typical to have another cell for specifying
flags if there is any kind of configuration for each irq line, like
edge vs. level and active high or active low. (the counter example is
PCI which doesn't use a flags cell because all PCI irqs are level
active.
You'll need to supply documentation for the ciu binding to
Documentation/devicetree/bindings before this patch gets merged.
> +unsigned int irq_create_of_mapping(struct device_node *controller,
> + const u32 *intspec, unsigned int intsize)
> +{
> + int ciu, bit;
> + unsigned int irq = 0;
> +
> + ciu = be32_to_cpup(intspec);
> + bit = be32_to_cpup(intspec + 1);
> +
> + if (ciu < 8 && bit < 64)
> + irq = octeon_irq_ciu_to_irq[ciu][bit];
> +
> + return irq;
> +}
> +EXPORT_SYMBOL_GPL(irq_create_of_mapping);
> +
> +
> static int octeon_coreid_for_cpu(int cpu)
> {
> #ifdef CONFIG_SMP
> --
> 1.7.2.3
>
^ permalink raw reply [flat|nested] 40+ messages in thread* Re: [RFC PATCH v2 06/12] MIPS: Octeon: Add a irq_create_of_mapping() implementation.
2011-03-05 1:07 ` Grant Likely
@ 2011-03-11 18:27 ` David Daney
0 siblings, 0 replies; 40+ messages in thread
From: David Daney @ 2011-03-11 18:27 UTC (permalink / raw)
To: Grant Likely; +Cc: linux-mips, ralf, devicetree-discuss, linux-kernel
On 03/04/2011 05:07 PM, Grant Likely wrote:
> On Fri, Mar 04, 2011 at 11:42:18AM -0800, David Daney wrote:
[...]
>> +/*
>> + * irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq#
>> + *
>> + * Octeon irq maps are a pair of indexes. The first selects either
>> + * ciu0 or ciu1, the second is the bit within the ciu register.
>> + */
>
> Is each 'ciu' an interrupt controller, or a 'bank' within the
> controller?
The ciu0 and ciu1 are 'banks' within a single interrupt controller.
Each of these 'banks' has 64 bits, each bit corresponds to the finest
grained source that can be routed via the interrupt infrastructure.
Each interrupt source can therefore be completely specified by its bank
and bit numbers.
> Also, it is typical to have another cell for specifying
> flags if there is any kind of configuration for each irq line, like
> edge vs. level and active high or active low. (the counter example is
> PCI which doesn't use a flags cell because all PCI irqs are level
> active.
>
If you look in patch 04/12, you will see that I have added such a flag
cell to the device tree. In the next revision of this patch, I will be
adding the logic to actually configure the polarity and triggering based
on the flag cell.
There are only 16 sources (GPIO pins that can actually be configured.
The remaining sources will ignore the triggering flags as they are hard
wired.
> You'll need to supply documentation for the ciu binding to
> Documentation/devicetree/bindings before this patch gets merged.
OK, I will work on that too.
Thanks,
David Daney
^ permalink raw reply [flat|nested] 40+ messages in thread
* [RFC PATCH v2 08/12] MIPS: Octeon: Initialize and fixup device tree.
2011-03-04 19:42 ` David Daney
@ 2011-03-04 19:42 ` David Daney
-1 siblings, 0 replies; 40+ messages in thread
From: David Daney @ 2011-03-04 19:42 UTC (permalink / raw)
To: linux-mips-6z/3iImG2C8G8FEW9MqTrA, ralf-6z/3iImG2C8G8FEW9MqTrA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
grant.likely-s3s/WqlpOiPyB63q8FvJNQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: David Daney
Signed-off-by: David Daney <ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8@public.gmane.org>
---
arch/mips/Kconfig | 1 +
arch/mips/cavium-octeon/octeon-platform.c | 234 +++++++++++++++++++++++++++++
arch/mips/cavium-octeon/setup.c | 17 ++
3 files changed, 252 insertions(+), 0 deletions(-)
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 4baf7f2..021be61 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1355,6 +1355,7 @@ config CPU_CAVIUM_OCTEON
select CPU_SUPPORTS_HIGHMEM
select CPU_SUPPORTS_HUGEPAGES
select GENERIC_HARDIRQS_NO_DEPRECATED
+ select LIBFDT
help
The Cavium Octeon processor is a highly integrated chip containing
many ethernet hardware widgets for networking tasks. The processor
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
index cecaf62..87512c5 100644
--- a/arch/mips/cavium-octeon/octeon-platform.c
+++ b/arch/mips/cavium-octeon/octeon-platform.c
@@ -13,10 +13,16 @@
#include <linux/usb.h>
#include <linux/dma-mapping.h>
#include <linux/module.h>
+#include <linux/slab.h>
#include <linux/platform_device.h>
+#include <linux/of_platform.h>
+#include <linux/of_fdt.h>
+#include <linux/libfdt.h>
#include <asm/octeon/octeon.h>
#include <asm/octeon/cvmx-rnm-defs.h>
+#include <asm/octeon/cvmx-helper.h>
+#include <asm/octeon/cvmx-helper-board.h>
static struct octeon_cf_data octeon_cf_data;
@@ -440,6 +446,234 @@ device_initcall(octeon_ohci_device_init);
#endif /* CONFIG_USB */
+static struct of_device_id __initdata octeon_ids[] = {
+ { .name = "soc@0", },
+ { .compatible = "simple-bus", },
+ {},
+};
+
+static void __init octeon_fdt_set_phy(int eth, int phy_addr)
+{
+ const __be32 *phy_handle;
+ const __be32 *reg;
+ struct fdt_node_header *raw_node;
+ u32 phandle;
+ int phy;
+ char new_address[3];
+ char *cp;
+
+ phy_handle = fdt_getprop(initial_boot_params, eth, "phy-handle", NULL);
+ if (!phy_handle)
+ return;
+
+ phandle = be32_to_cpup(phy_handle);
+ phy = fdt_node_offset_by_phandle(initial_boot_params, phandle);
+ if (phy_addr < 0 || phy < 0) {
+ /* Delete the PHY things */
+ if (phy >= 0)
+ fdt_nop_node(initial_boot_params, phy);
+ fdt_nop_property(initial_boot_params, eth, "phy-handle");
+ return;
+ }
+
+ reg = fdt_getprop(initial_boot_params, phy, "reg", NULL);
+ if (phy_addr == be32_to_cpup(reg))
+ return;
+
+ fdt_setprop_inplace_cell(initial_boot_params, phy, "reg", phy_addr);
+
+ snprintf(new_address, sizeof(new_address), "%x", phy_addr);
+ /*
+ * All PHYs in the template have a name like 'ethernet-phy@0',
+ * that is 14 characters, which allows us to replace the
+ * address portion with up to two characters without
+ * clobbering things past a multiple of 4 boundry.
+ */
+ raw_node = (void *)fdt_offset_ptr(initial_boot_params, phy, 0);
+ cp = strchr(raw_node->name, '@');
+ if (!cp)
+ return;
+ cp++;
+ cp[0] = new_address[0];
+ cp[1] = new_address[1];
+
+}
+
+static void __init octeon_fdt_set_mac_addr(int n, u64 *pmac)
+{
+ u8 new_mac[6];
+ u64 mac = *pmac;
+ int r;
+
+ new_mac[0] = (mac >> 40) & 0xff;
+ new_mac[1] = (mac >> 32) & 0xff;
+ new_mac[2] = (mac >> 24) & 0xff;
+ new_mac[3] = (mac >> 16) & 0xff;
+ new_mac[4] = (mac >> 8) & 0xff;
+ new_mac[5] = mac & 0xff;
+
+ r = fdt_setprop_inplace(initial_boot_params, n, "local-mac-address",
+ new_mac, sizeof(new_mac));
+
+ if (r) {
+ pr_err("Setting \"local-mac-address\" failed %d", r);
+ return;
+ }
+ *pmac = mac + 1;
+}
+
+static void __init octeon_fdt_rm_ethernet(int node)
+{
+ const __be32 *phy_handle;
+
+ phy_handle = fdt_getprop(initial_boot_params, node, "phy-handle", NULL);
+ if (phy_handle) {
+ u32 ph = be32_to_cpup(phy_handle);
+ int p = fdt_node_offset_by_phandle(initial_boot_params, ph);
+ if (p >= 0)
+ fdt_nop_node(initial_boot_params, p);
+ }
+ fdt_nop_node(initial_boot_params, node);
+}
+
+static void __init octeon_fdt_pip_port(int iface, int i, int p, u64 *pmac)
+{
+ char name_buffer[20];
+ int eth;
+ int phy_addr;
+
+ snprintf(name_buffer, sizeof(name_buffer), "ethernet@%d", p);
+ eth = fdt_subnode_offset(initial_boot_params, iface, name_buffer);
+ if (eth < 0)
+ return;
+ if (p >= cvmx_helper_ports_on_interface(i)) {
+ pr_notice("Deleting port %x:%x\n", i, p);
+ octeon_fdt_rm_ethernet(eth);
+ return;
+ }
+
+ phy_addr = cvmx_helper_board_get_mii_address(16 * i + p);
+ octeon_fdt_set_phy(eth, phy_addr);
+ octeon_fdt_set_mac_addr(eth, pmac);
+}
+
+static void __init octeon_fdt_pip_iface(int pip, int idx, u64 *pmac)
+{
+ char name_buffer[20];
+ int iface;
+ int p;
+
+ cvmx_helper_interface_enumerate(idx);
+ snprintf(name_buffer, sizeof(name_buffer), "interface@%d", idx);
+ iface = fdt_subnode_offset(initial_boot_params, pip, name_buffer);
+ if (iface < 0)
+ return;
+
+ for (p = 0; p < 4; p++)
+ octeon_fdt_pip_port(iface, idx, p, pmac);
+}
+
+int __init octeon_prune_device_tree(void)
+{
+ int i, max_port;
+ const char *pip_path;
+ char name_buffer[20];
+ int aliases;
+ u64 mac_addr_base;
+
+ if (fdt_check_header(initial_boot_params))
+ panic("Corrupt Device Tree.");
+
+ aliases = fdt_path_offset(initial_boot_params, "/aliases");
+ if (aliases < 0) {
+ pr_err("Error: No /aliases node in device tree.");
+ return -EINVAL;
+ }
+
+
+ mac_addr_base =
+ ((octeon_bootinfo->mac_addr_base[0] & 0xffull)) << 40 |
+ ((octeon_bootinfo->mac_addr_base[1] & 0xffull)) << 32 |
+ ((octeon_bootinfo->mac_addr_base[2] & 0xffull)) << 24 |
+ ((octeon_bootinfo->mac_addr_base[3] & 0xffull)) << 16 |
+ ((octeon_bootinfo->mac_addr_base[4] & 0xffull)) << 8 |
+ (octeon_bootinfo->mac_addr_base[5] & 0xffull);
+
+ if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN63XX))
+ max_port = 2;
+ else if (OCTEON_IS_MODEL(OCTEON_CN56XX))
+ max_port = 1;
+ else
+ max_port = 0;
+
+ for (i = 0; i < 2; i++) {
+ const char *alias_prop;
+ int mgmt;
+ snprintf(name_buffer, sizeof(name_buffer),
+ "mix%d", i);
+ alias_prop = fdt_getprop(initial_boot_params, aliases,
+ name_buffer, NULL);
+ if (alias_prop) {
+ mgmt = fdt_path_offset(initial_boot_params, alias_prop);
+ if (mgmt < 0)
+ continue;
+ if (i >= max_port) {
+ pr_notice("Deleting mix%d\n", i);
+ octeon_fdt_rm_ethernet(mgmt);
+ fdt_nop_property(initial_boot_params, aliases,
+ name_buffer);
+ } else {
+ octeon_fdt_set_phy(mgmt, i);
+ octeon_fdt_set_mac_addr(mgmt, &mac_addr_base);
+ }
+ }
+ }
+
+ pip_path = fdt_getprop(initial_boot_params, aliases, "pip", NULL);
+ if (pip_path) {
+ int pip = fdt_path_offset(initial_boot_params, pip_path);
+ if (pip >= 0)
+ for (i = 0; i < 4; i++)
+ octeon_fdt_pip_iface(pip, i, &mac_addr_base);
+ }
+
+ /* I2C */
+ if (OCTEON_IS_MODEL(OCTEON_CN52XX) ||
+ OCTEON_IS_MODEL(OCTEON_CN63XX) ||
+ OCTEON_IS_MODEL(OCTEON_CN56XX))
+ max_port = 2;
+ else
+ max_port = 1;
+
+ for (i = 0; i < 2; i++) {
+ const char *alias_prop;
+ int i2c;
+ snprintf(name_buffer, sizeof(name_buffer),
+ "twsi%d", i);
+ alias_prop = fdt_getprop(initial_boot_params, aliases,
+ name_buffer, NULL);
+
+ if (alias_prop) {
+ i2c = fdt_path_offset(initial_boot_params, alias_prop);
+ if (i2c < 0)
+ continue;
+ if (i >= max_port) {
+ pr_notice("Deleting i2c%d\n", i);
+ fdt_nop_node(initial_boot_params, i2c);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int __init octeon_publish_devices(void)
+{
+ return of_platform_bus_probe(NULL, octeon_ids, NULL);
+}
+device_initcall(octeon_publish_devices);
+
+
MODULE_AUTHOR("David Daney <ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8@public.gmane.org>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Platform driver for Octeon SOC");
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
index ab1a106..02765d6 100644
--- a/arch/mips/cavium-octeon/setup.c
+++ b/arch/mips/cavium-octeon/setup.c
@@ -20,6 +20,7 @@
#include <linux/platform_device.h>
#include <linux/serial_core.h>
#include <linux/serial_8250.h>
+#include <linux/of_fdt.h>
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/initrd.h>
#endif
@@ -797,3 +798,19 @@ void prom_free_prom_memory(void)
}
#endif
}
+
+int octeon_prune_device_tree(void);
+
+extern const char __dtb_octeon_3xxx_begin;
+extern const char __dtb_octeon_3xxx_end;
+void __init device_tree_init(void)
+{
+ int dt_size = &__dtb_octeon_3xxx_end - &__dtb_octeon_3xxx_begin;
+ /* Copy the default tree from init memory. */
+ initial_boot_params = early_init_dt_alloc_memory_arch(dt_size, 8);
+ if (initial_boot_params == NULL)
+ panic("Could not allocate initial_boot_params\n");
+ memcpy(initial_boot_params, &__dtb_octeon_3xxx_begin, dt_size);
+ octeon_prune_device_tree();
+ unflatten_device_tree();
+}
--
1.7.2.3
^ permalink raw reply related [flat|nested] 40+ messages in thread* [RFC PATCH v2 08/12] MIPS: Octeon: Initialize and fixup device tree.
@ 2011-03-04 19:42 ` David Daney
0 siblings, 0 replies; 40+ messages in thread
From: David Daney @ 2011-03-04 19:42 UTC (permalink / raw)
To: linux-mips, ralf, devicetree-discuss, grant.likely, linux-kernel
Cc: David Daney
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
---
arch/mips/Kconfig | 1 +
arch/mips/cavium-octeon/octeon-platform.c | 234 +++++++++++++++++++++++++++++
arch/mips/cavium-octeon/setup.c | 17 ++
3 files changed, 252 insertions(+), 0 deletions(-)
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 4baf7f2..021be61 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1355,6 +1355,7 @@ config CPU_CAVIUM_OCTEON
select CPU_SUPPORTS_HIGHMEM
select CPU_SUPPORTS_HUGEPAGES
select GENERIC_HARDIRQS_NO_DEPRECATED
+ select LIBFDT
help
The Cavium Octeon processor is a highly integrated chip containing
many ethernet hardware widgets for networking tasks. The processor
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
index cecaf62..87512c5 100644
--- a/arch/mips/cavium-octeon/octeon-platform.c
+++ b/arch/mips/cavium-octeon/octeon-platform.c
@@ -13,10 +13,16 @@
#include <linux/usb.h>
#include <linux/dma-mapping.h>
#include <linux/module.h>
+#include <linux/slab.h>
#include <linux/platform_device.h>
+#include <linux/of_platform.h>
+#include <linux/of_fdt.h>
+#include <linux/libfdt.h>
#include <asm/octeon/octeon.h>
#include <asm/octeon/cvmx-rnm-defs.h>
+#include <asm/octeon/cvmx-helper.h>
+#include <asm/octeon/cvmx-helper-board.h>
static struct octeon_cf_data octeon_cf_data;
@@ -440,6 +446,234 @@ device_initcall(octeon_ohci_device_init);
#endif /* CONFIG_USB */
+static struct of_device_id __initdata octeon_ids[] = {
+ { .name = "soc@0", },
+ { .compatible = "simple-bus", },
+ {},
+};
+
+static void __init octeon_fdt_set_phy(int eth, int phy_addr)
+{
+ const __be32 *phy_handle;
+ const __be32 *reg;
+ struct fdt_node_header *raw_node;
+ u32 phandle;
+ int phy;
+ char new_address[3];
+ char *cp;
+
+ phy_handle = fdt_getprop(initial_boot_params, eth, "phy-handle", NULL);
+ if (!phy_handle)
+ return;
+
+ phandle = be32_to_cpup(phy_handle);
+ phy = fdt_node_offset_by_phandle(initial_boot_params, phandle);
+ if (phy_addr < 0 || phy < 0) {
+ /* Delete the PHY things */
+ if (phy >= 0)
+ fdt_nop_node(initial_boot_params, phy);
+ fdt_nop_property(initial_boot_params, eth, "phy-handle");
+ return;
+ }
+
+ reg = fdt_getprop(initial_boot_params, phy, "reg", NULL);
+ if (phy_addr == be32_to_cpup(reg))
+ return;
+
+ fdt_setprop_inplace_cell(initial_boot_params, phy, "reg", phy_addr);
+
+ snprintf(new_address, sizeof(new_address), "%x", phy_addr);
+ /*
+ * All PHYs in the template have a name like 'ethernet-phy@0',
+ * that is 14 characters, which allows us to replace the
+ * address portion with up to two characters without
+ * clobbering things past a multiple of 4 boundry.
+ */
+ raw_node = (void *)fdt_offset_ptr(initial_boot_params, phy, 0);
+ cp = strchr(raw_node->name, '@');
+ if (!cp)
+ return;
+ cp++;
+ cp[0] = new_address[0];
+ cp[1] = new_address[1];
+
+}
+
+static void __init octeon_fdt_set_mac_addr(int n, u64 *pmac)
+{
+ u8 new_mac[6];
+ u64 mac = *pmac;
+ int r;
+
+ new_mac[0] = (mac >> 40) & 0xff;
+ new_mac[1] = (mac >> 32) & 0xff;
+ new_mac[2] = (mac >> 24) & 0xff;
+ new_mac[3] = (mac >> 16) & 0xff;
+ new_mac[4] = (mac >> 8) & 0xff;
+ new_mac[5] = mac & 0xff;
+
+ r = fdt_setprop_inplace(initial_boot_params, n, "local-mac-address",
+ new_mac, sizeof(new_mac));
+
+ if (r) {
+ pr_err("Setting \"local-mac-address\" failed %d", r);
+ return;
+ }
+ *pmac = mac + 1;
+}
+
+static void __init octeon_fdt_rm_ethernet(int node)
+{
+ const __be32 *phy_handle;
+
+ phy_handle = fdt_getprop(initial_boot_params, node, "phy-handle", NULL);
+ if (phy_handle) {
+ u32 ph = be32_to_cpup(phy_handle);
+ int p = fdt_node_offset_by_phandle(initial_boot_params, ph);
+ if (p >= 0)
+ fdt_nop_node(initial_boot_params, p);
+ }
+ fdt_nop_node(initial_boot_params, node);
+}
+
+static void __init octeon_fdt_pip_port(int iface, int i, int p, u64 *pmac)
+{
+ char name_buffer[20];
+ int eth;
+ int phy_addr;
+
+ snprintf(name_buffer, sizeof(name_buffer), "ethernet@%d", p);
+ eth = fdt_subnode_offset(initial_boot_params, iface, name_buffer);
+ if (eth < 0)
+ return;
+ if (p >= cvmx_helper_ports_on_interface(i)) {
+ pr_notice("Deleting port %x:%x\n", i, p);
+ octeon_fdt_rm_ethernet(eth);
+ return;
+ }
+
+ phy_addr = cvmx_helper_board_get_mii_address(16 * i + p);
+ octeon_fdt_set_phy(eth, phy_addr);
+ octeon_fdt_set_mac_addr(eth, pmac);
+}
+
+static void __init octeon_fdt_pip_iface(int pip, int idx, u64 *pmac)
+{
+ char name_buffer[20];
+ int iface;
+ int p;
+
+ cvmx_helper_interface_enumerate(idx);
+ snprintf(name_buffer, sizeof(name_buffer), "interface@%d", idx);
+ iface = fdt_subnode_offset(initial_boot_params, pip, name_buffer);
+ if (iface < 0)
+ return;
+
+ for (p = 0; p < 4; p++)
+ octeon_fdt_pip_port(iface, idx, p, pmac);
+}
+
+int __init octeon_prune_device_tree(void)
+{
+ int i, max_port;
+ const char *pip_path;
+ char name_buffer[20];
+ int aliases;
+ u64 mac_addr_base;
+
+ if (fdt_check_header(initial_boot_params))
+ panic("Corrupt Device Tree.");
+
+ aliases = fdt_path_offset(initial_boot_params, "/aliases");
+ if (aliases < 0) {
+ pr_err("Error: No /aliases node in device tree.");
+ return -EINVAL;
+ }
+
+
+ mac_addr_base =
+ ((octeon_bootinfo->mac_addr_base[0] & 0xffull)) << 40 |
+ ((octeon_bootinfo->mac_addr_base[1] & 0xffull)) << 32 |
+ ((octeon_bootinfo->mac_addr_base[2] & 0xffull)) << 24 |
+ ((octeon_bootinfo->mac_addr_base[3] & 0xffull)) << 16 |
+ ((octeon_bootinfo->mac_addr_base[4] & 0xffull)) << 8 |
+ (octeon_bootinfo->mac_addr_base[5] & 0xffull);
+
+ if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN63XX))
+ max_port = 2;
+ else if (OCTEON_IS_MODEL(OCTEON_CN56XX))
+ max_port = 1;
+ else
+ max_port = 0;
+
+ for (i = 0; i < 2; i++) {
+ const char *alias_prop;
+ int mgmt;
+ snprintf(name_buffer, sizeof(name_buffer),
+ "mix%d", i);
+ alias_prop = fdt_getprop(initial_boot_params, aliases,
+ name_buffer, NULL);
+ if (alias_prop) {
+ mgmt = fdt_path_offset(initial_boot_params, alias_prop);
+ if (mgmt < 0)
+ continue;
+ if (i >= max_port) {
+ pr_notice("Deleting mix%d\n", i);
+ octeon_fdt_rm_ethernet(mgmt);
+ fdt_nop_property(initial_boot_params, aliases,
+ name_buffer);
+ } else {
+ octeon_fdt_set_phy(mgmt, i);
+ octeon_fdt_set_mac_addr(mgmt, &mac_addr_base);
+ }
+ }
+ }
+
+ pip_path = fdt_getprop(initial_boot_params, aliases, "pip", NULL);
+ if (pip_path) {
+ int pip = fdt_path_offset(initial_boot_params, pip_path);
+ if (pip >= 0)
+ for (i = 0; i < 4; i++)
+ octeon_fdt_pip_iface(pip, i, &mac_addr_base);
+ }
+
+ /* I2C */
+ if (OCTEON_IS_MODEL(OCTEON_CN52XX) ||
+ OCTEON_IS_MODEL(OCTEON_CN63XX) ||
+ OCTEON_IS_MODEL(OCTEON_CN56XX))
+ max_port = 2;
+ else
+ max_port = 1;
+
+ for (i = 0; i < 2; i++) {
+ const char *alias_prop;
+ int i2c;
+ snprintf(name_buffer, sizeof(name_buffer),
+ "twsi%d", i);
+ alias_prop = fdt_getprop(initial_boot_params, aliases,
+ name_buffer, NULL);
+
+ if (alias_prop) {
+ i2c = fdt_path_offset(initial_boot_params, alias_prop);
+ if (i2c < 0)
+ continue;
+ if (i >= max_port) {
+ pr_notice("Deleting i2c%d\n", i);
+ fdt_nop_node(initial_boot_params, i2c);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int __init octeon_publish_devices(void)
+{
+ return of_platform_bus_probe(NULL, octeon_ids, NULL);
+}
+device_initcall(octeon_publish_devices);
+
+
MODULE_AUTHOR("David Daney <ddaney@caviumnetworks.com>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Platform driver for Octeon SOC");
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
index ab1a106..02765d6 100644
--- a/arch/mips/cavium-octeon/setup.c
+++ b/arch/mips/cavium-octeon/setup.c
@@ -20,6 +20,7 @@
#include <linux/platform_device.h>
#include <linux/serial_core.h>
#include <linux/serial_8250.h>
+#include <linux/of_fdt.h>
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/initrd.h>
#endif
@@ -797,3 +798,19 @@ void prom_free_prom_memory(void)
}
#endif
}
+
+int octeon_prune_device_tree(void);
+
+extern const char __dtb_octeon_3xxx_begin;
+extern const char __dtb_octeon_3xxx_end;
+void __init device_tree_init(void)
+{
+ int dt_size = &__dtb_octeon_3xxx_end - &__dtb_octeon_3xxx_begin;
+ /* Copy the default tree from init memory. */
+ initial_boot_params = early_init_dt_alloc_memory_arch(dt_size, 8);
+ if (initial_boot_params == NULL)
+ panic("Could not allocate initial_boot_params\n");
+ memcpy(initial_boot_params, &__dtb_octeon_3xxx_begin, dt_size);
+ octeon_prune_device_tree();
+ unflatten_device_tree();
+}
--
1.7.2.3
^ permalink raw reply related [flat|nested] 40+ messages in thread[parent not found: <1299267744-17278-9-git-send-email-ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8@public.gmane.org>]
* Re: [RFC PATCH v2 08/12] MIPS: Octeon: Initialize and fixup device tree.
2011-03-04 19:42 ` David Daney
@ 2011-03-05 3:05 ` Grant Likely
-1 siblings, 0 replies; 40+ messages in thread
From: Grant Likely @ 2011-03-05 3:05 UTC (permalink / raw)
To: David Daney
Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, ralf-6z/3iImG2C8G8FEW9MqTrA
On Fri, Mar 04, 2011 at 11:42:20AM -0800, David Daney wrote:
> Signed-off-by: David Daney <ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8@public.gmane.org>
> ---
> arch/mips/Kconfig | 1 +
> arch/mips/cavium-octeon/octeon-platform.c | 234 +++++++++++++++++++++++++++++
> arch/mips/cavium-octeon/setup.c | 17 ++
> 3 files changed, 252 insertions(+), 0 deletions(-)
>
> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> index 4baf7f2..021be61 100644
> --- a/arch/mips/Kconfig
> +++ b/arch/mips/Kconfig
> @@ -1355,6 +1355,7 @@ config CPU_CAVIUM_OCTEON
> select CPU_SUPPORTS_HIGHMEM
> select CPU_SUPPORTS_HUGEPAGES
> select GENERIC_HARDIRQS_NO_DEPRECATED
> + select LIBFDT
> help
> The Cavium Octeon processor is a highly integrated chip containing
> many ethernet hardware widgets for networking tasks. The processor
> diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
> index cecaf62..87512c5 100644
> --- a/arch/mips/cavium-octeon/octeon-platform.c
> +++ b/arch/mips/cavium-octeon/octeon-platform.c
> @@ -13,10 +13,16 @@
> #include <linux/usb.h>
> #include <linux/dma-mapping.h>
> #include <linux/module.h>
> +#include <linux/slab.h>
> #include <linux/platform_device.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_fdt.h>
> +#include <linux/libfdt.h>
>
> #include <asm/octeon/octeon.h>
> #include <asm/octeon/cvmx-rnm-defs.h>
> +#include <asm/octeon/cvmx-helper.h>
> +#include <asm/octeon/cvmx-helper-board.h>
>
> static struct octeon_cf_data octeon_cf_data;
>
> @@ -440,6 +446,234 @@ device_initcall(octeon_ohci_device_init);
>
> #endif /* CONFIG_USB */
>
> +static struct of_device_id __initdata octeon_ids[] = {
> + { .name = "soc@0", },
In general it is strongly discouraged to bind on name. It causes all
kinds of problems. Stick with simply binding on 'compatible'.
> + { .compatible = "simple-bus", },
> + {},
> +};
> +
> +static void __init octeon_fdt_set_phy(int eth, int phy_addr)
> +{
> + const __be32 *phy_handle;
> + const __be32 *reg;
> + struct fdt_node_header *raw_node;
> + u32 phandle;
> + int phy;
> + char new_address[3];
> + char *cp;
> +
> + phy_handle = fdt_getprop(initial_boot_params, eth, "phy-handle", NULL);
> + if (!phy_handle)
> + return;
> +
> + phandle = be32_to_cpup(phy_handle);
> + phy = fdt_node_offset_by_phandle(initial_boot_params, phandle);
> + if (phy_addr < 0 || phy < 0) {
> + /* Delete the PHY things */
> + if (phy >= 0)
> + fdt_nop_node(initial_boot_params, phy);
> + fdt_nop_property(initial_boot_params, eth, "phy-handle");
> + return;
> + }
> +
> + reg = fdt_getprop(initial_boot_params, phy, "reg", NULL);
> + if (phy_addr == be32_to_cpup(reg))
> + return;
> +
> + fdt_setprop_inplace_cell(initial_boot_params, phy, "reg", phy_addr);
> +
> + snprintf(new_address, sizeof(new_address), "%x", phy_addr);
> + /*
> + * All PHYs in the template have a name like 'ethernet-phy@0',
> + * that is 14 characters, which allows us to replace the
> + * address portion with up to two characters without
> + * clobbering things past a multiple of 4 boundry.
> + */
Yikes; that's just asking for trouble when someone changes the name in
the future without knowing about this code. You must do bounds checking.
> + raw_node = (void *)fdt_offset_ptr(initial_boot_params, phy, 0);
> + cp = strchr(raw_node->name, '@');
> + if (!cp)
> + return;
> + cp++;
> + cp[0] = new_address[0];
> + cp[1] = new_address[1];
> +
> +}
> +
> +static void __init octeon_fdt_set_mac_addr(int n, u64 *pmac)
> +{
> + u8 new_mac[6];
> + u64 mac = *pmac;
> + int r;
> +
> + new_mac[0] = (mac >> 40) & 0xff;
> + new_mac[1] = (mac >> 32) & 0xff;
> + new_mac[2] = (mac >> 24) & 0xff;
> + new_mac[3] = (mac >> 16) & 0xff;
> + new_mac[4] = (mac >> 8) & 0xff;
> + new_mac[5] = mac & 0xff;
> +
> + r = fdt_setprop_inplace(initial_boot_params, n, "local-mac-address",
> + new_mac, sizeof(new_mac));
> +
> + if (r) {
> + pr_err("Setting \"local-mac-address\" failed %d", r);
> + return;
> + }
> + *pmac = mac + 1;
> +}
> +
> +static void __init octeon_fdt_rm_ethernet(int node)
> +{
> + const __be32 *phy_handle;
> +
> + phy_handle = fdt_getprop(initial_boot_params, node, "phy-handle", NULL);
> + if (phy_handle) {
> + u32 ph = be32_to_cpup(phy_handle);
> + int p = fdt_node_offset_by_phandle(initial_boot_params, ph);
> + if (p >= 0)
> + fdt_nop_node(initial_boot_params, p);
> + }
> + fdt_nop_node(initial_boot_params, node);
> +}
> +
> +static void __init octeon_fdt_pip_port(int iface, int i, int p, u64 *pmac)
> +{
> + char name_buffer[20];
> + int eth;
> + int phy_addr;
> +
> + snprintf(name_buffer, sizeof(name_buffer), "ethernet@%d", p);
> + eth = fdt_subnode_offset(initial_boot_params, iface, name_buffer);
> + if (eth < 0)
> + return;
> + if (p >= cvmx_helper_ports_on_interface(i)) {
> + pr_notice("Deleting port %x:%x\n", i, p);
> + octeon_fdt_rm_ethernet(eth);
> + return;
> + }
> +
> + phy_addr = cvmx_helper_board_get_mii_address(16 * i + p);
> + octeon_fdt_set_phy(eth, phy_addr);
> + octeon_fdt_set_mac_addr(eth, pmac);
> +}
> +
> +static void __init octeon_fdt_pip_iface(int pip, int idx, u64 *pmac)
> +{
> + char name_buffer[20];
> + int iface;
> + int p;
> +
> + cvmx_helper_interface_enumerate(idx);
> + snprintf(name_buffer, sizeof(name_buffer), "interface@%d", idx);
> + iface = fdt_subnode_offset(initial_boot_params, pip, name_buffer);
> + if (iface < 0)
> + return;
> +
> + for (p = 0; p < 4; p++)
> + octeon_fdt_pip_port(iface, idx, p, pmac);
> +}
> +
> +int __init octeon_prune_device_tree(void)
> +{
> + int i, max_port;
> + const char *pip_path;
> + char name_buffer[20];
> + int aliases;
> + u64 mac_addr_base;
> +
> + if (fdt_check_header(initial_boot_params))
> + panic("Corrupt Device Tree.");
> +
> + aliases = fdt_path_offset(initial_boot_params, "/aliases");
> + if (aliases < 0) {
> + pr_err("Error: No /aliases node in device tree.");
> + return -EINVAL;
> + }
> +
> +
> + mac_addr_base =
> + ((octeon_bootinfo->mac_addr_base[0] & 0xffull)) << 40 |
> + ((octeon_bootinfo->mac_addr_base[1] & 0xffull)) << 32 |
> + ((octeon_bootinfo->mac_addr_base[2] & 0xffull)) << 24 |
> + ((octeon_bootinfo->mac_addr_base[3] & 0xffull)) << 16 |
> + ((octeon_bootinfo->mac_addr_base[4] & 0xffull)) << 8 |
> + (octeon_bootinfo->mac_addr_base[5] & 0xffull);
> +
> + if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN63XX))
> + max_port = 2;
> + else if (OCTEON_IS_MODEL(OCTEON_CN56XX))
> + max_port = 1;
> + else
> + max_port = 0;
> +
> + for (i = 0; i < 2; i++) {
> + const char *alias_prop;
> + int mgmt;
> + snprintf(name_buffer, sizeof(name_buffer),
> + "mix%d", i);
> + alias_prop = fdt_getprop(initial_boot_params, aliases,
> + name_buffer, NULL);
> + if (alias_prop) {
> + mgmt = fdt_path_offset(initial_boot_params, alias_prop);
> + if (mgmt < 0)
> + continue;
> + if (i >= max_port) {
> + pr_notice("Deleting mix%d\n", i);
> + octeon_fdt_rm_ethernet(mgmt);
> + fdt_nop_property(initial_boot_params, aliases,
> + name_buffer);
> + } else {
> + octeon_fdt_set_phy(mgmt, i);
> + octeon_fdt_set_mac_addr(mgmt, &mac_addr_base);
> + }
> + }
> + }
> +
> + pip_path = fdt_getprop(initial_boot_params, aliases, "pip", NULL);
> + if (pip_path) {
> + int pip = fdt_path_offset(initial_boot_params, pip_path);
> + if (pip >= 0)
> + for (i = 0; i < 4; i++)
> + octeon_fdt_pip_iface(pip, i, &mac_addr_base);
> + }
> +
> + /* I2C */
> + if (OCTEON_IS_MODEL(OCTEON_CN52XX) ||
> + OCTEON_IS_MODEL(OCTEON_CN63XX) ||
> + OCTEON_IS_MODEL(OCTEON_CN56XX))
> + max_port = 2;
> + else
> + max_port = 1;
> +
> + for (i = 0; i < 2; i++) {
> + const char *alias_prop;
> + int i2c;
> + snprintf(name_buffer, sizeof(name_buffer),
> + "twsi%d", i);
> + alias_prop = fdt_getprop(initial_boot_params, aliases,
> + name_buffer, NULL);
> +
> + if (alias_prop) {
> + i2c = fdt_path_offset(initial_boot_params, alias_prop);
> + if (i2c < 0)
> + continue;
> + if (i >= max_port) {
> + pr_notice("Deleting i2c%d\n", i);
> + fdt_nop_node(initial_boot_params, i2c);
> + }
> + }
> + }
> +
> + return 0;
> +}
> +
> +static int __init octeon_publish_devices(void)
> +{
> + return of_platform_bus_probe(NULL, octeon_ids, NULL);
> +}
> +device_initcall(octeon_publish_devices);
> +
> +
> MODULE_AUTHOR("David Daney <ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8@public.gmane.org>");
> MODULE_LICENSE("GPL");
> MODULE_DESCRIPTION("Platform driver for Octeon SOC");
> diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
> index ab1a106..02765d6 100644
> --- a/arch/mips/cavium-octeon/setup.c
> +++ b/arch/mips/cavium-octeon/setup.c
> @@ -20,6 +20,7 @@
> #include <linux/platform_device.h>
> #include <linux/serial_core.h>
> #include <linux/serial_8250.h>
> +#include <linux/of_fdt.h>
> #ifdef CONFIG_BLK_DEV_INITRD
> #include <linux/initrd.h>
> #endif
> @@ -797,3 +798,19 @@ void prom_free_prom_memory(void)
> }
> #endif
> }
> +
> +int octeon_prune_device_tree(void);
> +
> +extern const char __dtb_octeon_3xxx_begin;
> +extern const char __dtb_octeon_3xxx_end;
> +void __init device_tree_init(void)
> +{
> + int dt_size = &__dtb_octeon_3xxx_end - &__dtb_octeon_3xxx_begin;
> + /* Copy the default tree from init memory. */
> + initial_boot_params = early_init_dt_alloc_memory_arch(dt_size, 8);
> + if (initial_boot_params == NULL)
> + panic("Could not allocate initial_boot_params\n");
> + memcpy(initial_boot_params, &__dtb_octeon_3xxx_begin, dt_size);
> + octeon_prune_device_tree();
> + unflatten_device_tree();
> +}
> --
> 1.7.2.3
>
^ permalink raw reply [flat|nested] 40+ messages in thread* Re: [RFC PATCH v2 08/12] MIPS: Octeon: Initialize and fixup device tree.
@ 2011-03-05 3:05 ` Grant Likely
0 siblings, 0 replies; 40+ messages in thread
From: Grant Likely @ 2011-03-05 3:05 UTC (permalink / raw)
To: David Daney; +Cc: linux-mips, ralf, devicetree-discuss, linux-kernel
On Fri, Mar 04, 2011 at 11:42:20AM -0800, David Daney wrote:
> Signed-off-by: David Daney <ddaney@caviumnetworks.com>
> ---
> arch/mips/Kconfig | 1 +
> arch/mips/cavium-octeon/octeon-platform.c | 234 +++++++++++++++++++++++++++++
> arch/mips/cavium-octeon/setup.c | 17 ++
> 3 files changed, 252 insertions(+), 0 deletions(-)
>
> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> index 4baf7f2..021be61 100644
> --- a/arch/mips/Kconfig
> +++ b/arch/mips/Kconfig
> @@ -1355,6 +1355,7 @@ config CPU_CAVIUM_OCTEON
> select CPU_SUPPORTS_HIGHMEM
> select CPU_SUPPORTS_HUGEPAGES
> select GENERIC_HARDIRQS_NO_DEPRECATED
> + select LIBFDT
> help
> The Cavium Octeon processor is a highly integrated chip containing
> many ethernet hardware widgets for networking tasks. The processor
> diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
> index cecaf62..87512c5 100644
> --- a/arch/mips/cavium-octeon/octeon-platform.c
> +++ b/arch/mips/cavium-octeon/octeon-platform.c
> @@ -13,10 +13,16 @@
> #include <linux/usb.h>
> #include <linux/dma-mapping.h>
> #include <linux/module.h>
> +#include <linux/slab.h>
> #include <linux/platform_device.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_fdt.h>
> +#include <linux/libfdt.h>
>
> #include <asm/octeon/octeon.h>
> #include <asm/octeon/cvmx-rnm-defs.h>
> +#include <asm/octeon/cvmx-helper.h>
> +#include <asm/octeon/cvmx-helper-board.h>
>
> static struct octeon_cf_data octeon_cf_data;
>
> @@ -440,6 +446,234 @@ device_initcall(octeon_ohci_device_init);
>
> #endif /* CONFIG_USB */
>
> +static struct of_device_id __initdata octeon_ids[] = {
> + { .name = "soc@0", },
In general it is strongly discouraged to bind on name. It causes all
kinds of problems. Stick with simply binding on 'compatible'.
> + { .compatible = "simple-bus", },
> + {},
> +};
> +
> +static void __init octeon_fdt_set_phy(int eth, int phy_addr)
> +{
> + const __be32 *phy_handle;
> + const __be32 *reg;
> + struct fdt_node_header *raw_node;
> + u32 phandle;
> + int phy;
> + char new_address[3];
> + char *cp;
> +
> + phy_handle = fdt_getprop(initial_boot_params, eth, "phy-handle", NULL);
> + if (!phy_handle)
> + return;
> +
> + phandle = be32_to_cpup(phy_handle);
> + phy = fdt_node_offset_by_phandle(initial_boot_params, phandle);
> + if (phy_addr < 0 || phy < 0) {
> + /* Delete the PHY things */
> + if (phy >= 0)
> + fdt_nop_node(initial_boot_params, phy);
> + fdt_nop_property(initial_boot_params, eth, "phy-handle");
> + return;
> + }
> +
> + reg = fdt_getprop(initial_boot_params, phy, "reg", NULL);
> + if (phy_addr == be32_to_cpup(reg))
> + return;
> +
> + fdt_setprop_inplace_cell(initial_boot_params, phy, "reg", phy_addr);
> +
> + snprintf(new_address, sizeof(new_address), "%x", phy_addr);
> + /*
> + * All PHYs in the template have a name like 'ethernet-phy@0',
> + * that is 14 characters, which allows us to replace the
> + * address portion with up to two characters without
> + * clobbering things past a multiple of 4 boundry.
> + */
Yikes; that's just asking for trouble when someone changes the name in
the future without knowing about this code. You must do bounds checking.
> + raw_node = (void *)fdt_offset_ptr(initial_boot_params, phy, 0);
> + cp = strchr(raw_node->name, '@');
> + if (!cp)
> + return;
> + cp++;
> + cp[0] = new_address[0];
> + cp[1] = new_address[1];
> +
> +}
> +
> +static void __init octeon_fdt_set_mac_addr(int n, u64 *pmac)
> +{
> + u8 new_mac[6];
> + u64 mac = *pmac;
> + int r;
> +
> + new_mac[0] = (mac >> 40) & 0xff;
> + new_mac[1] = (mac >> 32) & 0xff;
> + new_mac[2] = (mac >> 24) & 0xff;
> + new_mac[3] = (mac >> 16) & 0xff;
> + new_mac[4] = (mac >> 8) & 0xff;
> + new_mac[5] = mac & 0xff;
> +
> + r = fdt_setprop_inplace(initial_boot_params, n, "local-mac-address",
> + new_mac, sizeof(new_mac));
> +
> + if (r) {
> + pr_err("Setting \"local-mac-address\" failed %d", r);
> + return;
> + }
> + *pmac = mac + 1;
> +}
> +
> +static void __init octeon_fdt_rm_ethernet(int node)
> +{
> + const __be32 *phy_handle;
> +
> + phy_handle = fdt_getprop(initial_boot_params, node, "phy-handle", NULL);
> + if (phy_handle) {
> + u32 ph = be32_to_cpup(phy_handle);
> + int p = fdt_node_offset_by_phandle(initial_boot_params, ph);
> + if (p >= 0)
> + fdt_nop_node(initial_boot_params, p);
> + }
> + fdt_nop_node(initial_boot_params, node);
> +}
> +
> +static void __init octeon_fdt_pip_port(int iface, int i, int p, u64 *pmac)
> +{
> + char name_buffer[20];
> + int eth;
> + int phy_addr;
> +
> + snprintf(name_buffer, sizeof(name_buffer), "ethernet@%d", p);
> + eth = fdt_subnode_offset(initial_boot_params, iface, name_buffer);
> + if (eth < 0)
> + return;
> + if (p >= cvmx_helper_ports_on_interface(i)) {
> + pr_notice("Deleting port %x:%x\n", i, p);
> + octeon_fdt_rm_ethernet(eth);
> + return;
> + }
> +
> + phy_addr = cvmx_helper_board_get_mii_address(16 * i + p);
> + octeon_fdt_set_phy(eth, phy_addr);
> + octeon_fdt_set_mac_addr(eth, pmac);
> +}
> +
> +static void __init octeon_fdt_pip_iface(int pip, int idx, u64 *pmac)
> +{
> + char name_buffer[20];
> + int iface;
> + int p;
> +
> + cvmx_helper_interface_enumerate(idx);
> + snprintf(name_buffer, sizeof(name_buffer), "interface@%d", idx);
> + iface = fdt_subnode_offset(initial_boot_params, pip, name_buffer);
> + if (iface < 0)
> + return;
> +
> + for (p = 0; p < 4; p++)
> + octeon_fdt_pip_port(iface, idx, p, pmac);
> +}
> +
> +int __init octeon_prune_device_tree(void)
> +{
> + int i, max_port;
> + const char *pip_path;
> + char name_buffer[20];
> + int aliases;
> + u64 mac_addr_base;
> +
> + if (fdt_check_header(initial_boot_params))
> + panic("Corrupt Device Tree.");
> +
> + aliases = fdt_path_offset(initial_boot_params, "/aliases");
> + if (aliases < 0) {
> + pr_err("Error: No /aliases node in device tree.");
> + return -EINVAL;
> + }
> +
> +
> + mac_addr_base =
> + ((octeon_bootinfo->mac_addr_base[0] & 0xffull)) << 40 |
> + ((octeon_bootinfo->mac_addr_base[1] & 0xffull)) << 32 |
> + ((octeon_bootinfo->mac_addr_base[2] & 0xffull)) << 24 |
> + ((octeon_bootinfo->mac_addr_base[3] & 0xffull)) << 16 |
> + ((octeon_bootinfo->mac_addr_base[4] & 0xffull)) << 8 |
> + (octeon_bootinfo->mac_addr_base[5] & 0xffull);
> +
> + if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN63XX))
> + max_port = 2;
> + else if (OCTEON_IS_MODEL(OCTEON_CN56XX))
> + max_port = 1;
> + else
> + max_port = 0;
> +
> + for (i = 0; i < 2; i++) {
> + const char *alias_prop;
> + int mgmt;
> + snprintf(name_buffer, sizeof(name_buffer),
> + "mix%d", i);
> + alias_prop = fdt_getprop(initial_boot_params, aliases,
> + name_buffer, NULL);
> + if (alias_prop) {
> + mgmt = fdt_path_offset(initial_boot_params, alias_prop);
> + if (mgmt < 0)
> + continue;
> + if (i >= max_port) {
> + pr_notice("Deleting mix%d\n", i);
> + octeon_fdt_rm_ethernet(mgmt);
> + fdt_nop_property(initial_boot_params, aliases,
> + name_buffer);
> + } else {
> + octeon_fdt_set_phy(mgmt, i);
> + octeon_fdt_set_mac_addr(mgmt, &mac_addr_base);
> + }
> + }
> + }
> +
> + pip_path = fdt_getprop(initial_boot_params, aliases, "pip", NULL);
> + if (pip_path) {
> + int pip = fdt_path_offset(initial_boot_params, pip_path);
> + if (pip >= 0)
> + for (i = 0; i < 4; i++)
> + octeon_fdt_pip_iface(pip, i, &mac_addr_base);
> + }
> +
> + /* I2C */
> + if (OCTEON_IS_MODEL(OCTEON_CN52XX) ||
> + OCTEON_IS_MODEL(OCTEON_CN63XX) ||
> + OCTEON_IS_MODEL(OCTEON_CN56XX))
> + max_port = 2;
> + else
> + max_port = 1;
> +
> + for (i = 0; i < 2; i++) {
> + const char *alias_prop;
> + int i2c;
> + snprintf(name_buffer, sizeof(name_buffer),
> + "twsi%d", i);
> + alias_prop = fdt_getprop(initial_boot_params, aliases,
> + name_buffer, NULL);
> +
> + if (alias_prop) {
> + i2c = fdt_path_offset(initial_boot_params, alias_prop);
> + if (i2c < 0)
> + continue;
> + if (i >= max_port) {
> + pr_notice("Deleting i2c%d\n", i);
> + fdt_nop_node(initial_boot_params, i2c);
> + }
> + }
> + }
> +
> + return 0;
> +}
> +
> +static int __init octeon_publish_devices(void)
> +{
> + return of_platform_bus_probe(NULL, octeon_ids, NULL);
> +}
> +device_initcall(octeon_publish_devices);
> +
> +
> MODULE_AUTHOR("David Daney <ddaney@caviumnetworks.com>");
> MODULE_LICENSE("GPL");
> MODULE_DESCRIPTION("Platform driver for Octeon SOC");
> diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
> index ab1a106..02765d6 100644
> --- a/arch/mips/cavium-octeon/setup.c
> +++ b/arch/mips/cavium-octeon/setup.c
> @@ -20,6 +20,7 @@
> #include <linux/platform_device.h>
> #include <linux/serial_core.h>
> #include <linux/serial_8250.h>
> +#include <linux/of_fdt.h>
> #ifdef CONFIG_BLK_DEV_INITRD
> #include <linux/initrd.h>
> #endif
> @@ -797,3 +798,19 @@ void prom_free_prom_memory(void)
> }
> #endif
> }
> +
> +int octeon_prune_device_tree(void);
> +
> +extern const char __dtb_octeon_3xxx_begin;
> +extern const char __dtb_octeon_3xxx_end;
> +void __init device_tree_init(void)
> +{
> + int dt_size = &__dtb_octeon_3xxx_end - &__dtb_octeon_3xxx_begin;
> + /* Copy the default tree from init memory. */
> + initial_boot_params = early_init_dt_alloc_memory_arch(dt_size, 8);
> + if (initial_boot_params == NULL)
> + panic("Could not allocate initial_boot_params\n");
> + memcpy(initial_boot_params, &__dtb_octeon_3xxx_begin, dt_size);
> + octeon_prune_device_tree();
> + unflatten_device_tree();
> +}
> --
> 1.7.2.3
>
^ permalink raw reply [flat|nested] 40+ messages in thread
* [RFC PATCH v2 09/12] i2c: Convert i2c-octeon.c to use device tree.
2011-03-04 19:42 ` David Daney
@ 2011-03-04 19:42 ` David Daney
-1 siblings, 0 replies; 40+ messages in thread
From: David Daney @ 2011-03-04 19:42 UTC (permalink / raw)
To: linux-mips-6z/3iImG2C8G8FEW9MqTrA, ralf-6z/3iImG2C8G8FEW9MqTrA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
grant.likely-s3s/WqlpOiPyB63q8FvJNQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: Jean Delvare (PC drivers, core), David Daney,
Ben Dooks (embedded platforms), linux-i2c-u79uwXL29TY76Z2rM5mHXA
Signed-off-by: David Daney <ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8@public.gmane.org>
Cc: "Jean Delvare (PC drivers, core)" <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
Cc: "Ben Dooks (embedded platforms)" <ben-linux-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org>
Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
---
arch/mips/cavium-octeon/octeon-platform.c | 84 -----------------------------
arch/mips/include/asm/octeon/octeon.h | 5 --
drivers/i2c/busses/i2c-octeon.c | 69 ++++++++++++++----------
3 files changed, 41 insertions(+), 117 deletions(-)
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
index 87512c5..0533351 100644
--- a/arch/mips/cavium-octeon/octeon-platform.c
+++ b/arch/mips/cavium-octeon/octeon-platform.c
@@ -168,90 +168,6 @@ out:
}
device_initcall(octeon_rng_device_init);
-static struct i2c_board_info __initdata octeon_i2c_devices[] = {
- {
- I2C_BOARD_INFO("ds1337", 0x68),
- },
-};
-
-static int __init octeon_i2c_devices_init(void)
-{
- return i2c_register_board_info(0, octeon_i2c_devices,
- ARRAY_SIZE(octeon_i2c_devices));
-}
-arch_initcall(octeon_i2c_devices_init);
-
-#define OCTEON_I2C_IO_BASE 0x1180000001000ull
-#define OCTEON_I2C_IO_UNIT_OFFSET 0x200
-
-static struct octeon_i2c_data octeon_i2c_data[2];
-
-static int __init octeon_i2c_device_init(void)
-{
- struct platform_device *pd;
- int ret = 0;
- int port, num_ports;
-
- struct resource i2c_resources[] = {
- {
- .flags = IORESOURCE_MEM,
- }, {
- .flags = IORESOURCE_IRQ,
- }
- };
-
- if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
- num_ports = 2;
- else
- num_ports = 1;
-
- for (port = 0; port < num_ports; port++) {
- octeon_i2c_data[port].sys_freq = octeon_get_io_clock_rate();
- /*FIXME: should be examined. At the moment is set for 100Khz */
- octeon_i2c_data[port].i2c_freq = 100000;
-
- pd = platform_device_alloc("i2c-octeon", port);
- if (!pd) {
- ret = -ENOMEM;
- goto out;
- }
-
- pd->dev.platform_data = octeon_i2c_data + port;
-
- i2c_resources[0].start =
- OCTEON_I2C_IO_BASE + (port * OCTEON_I2C_IO_UNIT_OFFSET);
- i2c_resources[0].end = i2c_resources[0].start + 0x1f;
- switch (port) {
- case 0:
- i2c_resources[1].start = OCTEON_IRQ_TWSI;
- i2c_resources[1].end = OCTEON_IRQ_TWSI;
- break;
- case 1:
- i2c_resources[1].start = OCTEON_IRQ_TWSI2;
- i2c_resources[1].end = OCTEON_IRQ_TWSI2;
- break;
- default:
- BUG();
- }
-
- ret = platform_device_add_resources(pd,
- i2c_resources,
- ARRAY_SIZE(i2c_resources));
- if (ret)
- goto fail;
-
- ret = platform_device_add(pd);
- if (ret)
- goto fail;
- }
- return ret;
-fail:
- platform_device_put(pd);
-out:
- return ret;
-}
-device_initcall(octeon_i2c_device_init);
-
/* Octeon SMI/MDIO interface. */
static int __init octeon_mdiobus_device_init(void)
{
diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h
index f72f768..1e2486e 100644
--- a/arch/mips/include/asm/octeon/octeon.h
+++ b/arch/mips/include/asm/octeon/octeon.h
@@ -215,11 +215,6 @@ struct octeon_cf_data {
int dma_engine; /* -1 for no DMA */
};
-struct octeon_i2c_data {
- unsigned int sys_freq;
- unsigned int i2c_freq;
-};
-
extern void octeon_write_lcd(const char *s);
extern void octeon_check_cpu_bist(void);
extern int octeon_get_boot_debug_flag(void);
diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
index 56dbe54..cb34725 100644
--- a/drivers/i2c/busses/i2c-octeon.c
+++ b/drivers/i2c/busses/i2c-octeon.c
@@ -2,7 +2,7 @@
* (C) Copyright 2009-2010
* Nokia Siemens Networks, michael.lawnick.ext-OYasijW0DpE@public.gmane.org
*
- * Portions Copyright (C) 2010 Cavium Networks, Inc.
+ * Portions Copyright (C) 2010, 2011 Cavium Networks, Inc.
*
* This is a driver for the i2c adapter in Cavium Networks' OCTEON processors.
*
@@ -11,17 +11,18 @@
* warranty of any kind, whether express or implied.
*/
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/of_i2c.h>
+#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/init.h>
-
-#include <linux/io.h>
#include <linux/i2c.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/of.h>
#include <asm/octeon/octeon.h>
@@ -121,10 +122,8 @@ static u8 octeon_i2c_read_sw(struct octeon_i2c *i2c, u64 eop_reg)
*/
static void octeon_i2c_write_int(struct octeon_i2c *i2c, u64 data)
{
- u64 tmp;
-
__raw_writeq(data, i2c->twsi_base + TWSI_INT);
- tmp = __raw_readq(i2c->twsi_base + TWSI_INT);
+ __raw_readq(i2c->twsi_base + TWSI_INT);
}
/**
@@ -515,22 +514,22 @@ static int __devinit octeon_i2c_probe(struct platform_device *pdev)
{
int irq, result = 0;
struct octeon_i2c *i2c;
- struct octeon_i2c_data *i2c_data;
struct resource *res_mem;
+ const __be32 *data;
+ int len;
/* All adaptors have an irq. */
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
- i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
+ i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
if (!i2c) {
dev_err(&pdev->dev, "kzalloc failed\n");
result = -ENOMEM;
goto out;
}
i2c->dev = &pdev->dev;
- i2c_data = pdev->dev.platform_data;
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -539,19 +538,22 @@ static int __devinit octeon_i2c_probe(struct platform_device *pdev)
result = -ENXIO;
goto fail_region;
}
+ i2c->twsi_phys = res_mem->start;
+ i2c->regsize = resource_size(res_mem);
- if (i2c_data == NULL) {
- dev_err(i2c->dev, "no I2C frequency data\n");
+ data = of_get_property(pdev->dev.of_node, "clock-rate", &len);
+ if (data && len == sizeof(*data)) {
+ i2c->twsi_freq = be32_to_cpup(data);
+ } else {
+ dev_err(i2c->dev, "no I2C 'clock-rate' property\n");
result = -ENXIO;
goto fail_region;
}
- i2c->twsi_phys = res_mem->start;
- i2c->regsize = resource_size(res_mem);
- i2c->twsi_freq = i2c_data->i2c_freq;
- i2c->sys_freq = i2c_data->sys_freq;
+ i2c->sys_freq = octeon_get_io_clock_rate();
- if (!request_mem_region(i2c->twsi_phys, i2c->regsize, res_mem->name)) {
+ if (!devm_request_mem_region(&pdev->dev, i2c->twsi_phys, i2c->regsize,
+ res_mem->name)) {
dev_err(i2c->dev, "request_mem_region failed\n");
goto fail_region;
}
@@ -581,28 +583,31 @@ static int __devinit octeon_i2c_probe(struct platform_device *pdev)
i2c->adap = octeon_i2c_ops;
i2c->adap.dev.parent = &pdev->dev;
- i2c->adap.nr = pdev->id >= 0 ? pdev->id : 0;
+ i2c->adap.dev.of_node = pdev->dev.of_node;
i2c_set_adapdata(&i2c->adap, i2c);
platform_set_drvdata(pdev, i2c);
- result = i2c_add_numbered_adapter(&i2c->adap);
+ result = i2c_add_adapter(&i2c->adap);
if (result < 0) {
dev_err(i2c->dev, "failed to add adapter\n");
goto fail_add;
}
-
dev_info(i2c->dev, "version %s\n", DRV_VERSION);
- return result;
+ of_i2c_register_devices(&i2c->adap);
+
+ return 0;
fail_add:
platform_set_drvdata(pdev, NULL);
free_irq(i2c->irq, i2c);
fail_irq:
iounmap(i2c->twsi_base);
- release_mem_region(i2c->twsi_phys, i2c->regsize);
+
+ devm_release_mem_region(&pdev->dev, i2c->twsi_phys, i2c->regsize);
fail_region:
- kfree(i2c);
+
+ devm_kfree(&pdev->dev, i2c);
out:
return result;
};
@@ -615,17 +620,26 @@ static int __devexit octeon_i2c_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
free_irq(i2c->irq, i2c);
iounmap(i2c->twsi_base);
- release_mem_region(i2c->twsi_phys, i2c->regsize);
- kfree(i2c);
+ devm_release_mem_region(&pdev->dev, i2c->twsi_phys, i2c->regsize);
+ devm_kfree(&pdev->dev, i2c);
return 0;
};
+static struct of_device_id octeon_i2c_match[] = {
+ {
+ .compatible = "cavium,octeon-3860-twsi",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, octeon_i2c_match);
+
static struct platform_driver octeon_i2c_driver = {
.probe = octeon_i2c_probe,
.remove = __devexit_p(octeon_i2c_remove),
.driver = {
.owner = THIS_MODULE,
.name = DRV_NAME,
+ .of_match_table = octeon_i2c_match,
},
};
@@ -646,7 +660,6 @@ MODULE_AUTHOR("Michael Lawnick <michael.lawnick.ext-OYasijW0DpE@public.gmane.org>");
MODULE_DESCRIPTION("I2C-Bus adapter for Cavium OCTEON processors");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
-MODULE_ALIAS("platform:" DRV_NAME);
module_init(octeon_i2c_init);
module_exit(octeon_i2c_exit);
--
1.7.2.3
^ permalink raw reply related [flat|nested] 40+ messages in thread* [RFC PATCH v2 09/12] i2c: Convert i2c-octeon.c to use device tree.
@ 2011-03-04 19:42 ` David Daney
0 siblings, 0 replies; 40+ messages in thread
From: David Daney @ 2011-03-04 19:42 UTC (permalink / raw)
To: linux-mips, ralf, devicetree-discuss, grant.likely, linux-kernel
Cc: David Daney, Jean Delvare (PC drivers, core),
Ben Dooks (embedded platforms), linux-i2c
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Cc: "Jean Delvare (PC drivers, core)" <khali@linux-fr.org>
Cc: "Ben Dooks (embedded platforms)" <ben-linux@fluff.org>
Cc: linux-i2c@vger.kernel.org
---
arch/mips/cavium-octeon/octeon-platform.c | 84 -----------------------------
arch/mips/include/asm/octeon/octeon.h | 5 --
drivers/i2c/busses/i2c-octeon.c | 69 ++++++++++++++----------
3 files changed, 41 insertions(+), 117 deletions(-)
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
index 87512c5..0533351 100644
--- a/arch/mips/cavium-octeon/octeon-platform.c
+++ b/arch/mips/cavium-octeon/octeon-platform.c
@@ -168,90 +168,6 @@ out:
}
device_initcall(octeon_rng_device_init);
-static struct i2c_board_info __initdata octeon_i2c_devices[] = {
- {
- I2C_BOARD_INFO("ds1337", 0x68),
- },
-};
-
-static int __init octeon_i2c_devices_init(void)
-{
- return i2c_register_board_info(0, octeon_i2c_devices,
- ARRAY_SIZE(octeon_i2c_devices));
-}
-arch_initcall(octeon_i2c_devices_init);
-
-#define OCTEON_I2C_IO_BASE 0x1180000001000ull
-#define OCTEON_I2C_IO_UNIT_OFFSET 0x200
-
-static struct octeon_i2c_data octeon_i2c_data[2];
-
-static int __init octeon_i2c_device_init(void)
-{
- struct platform_device *pd;
- int ret = 0;
- int port, num_ports;
-
- struct resource i2c_resources[] = {
- {
- .flags = IORESOURCE_MEM,
- }, {
- .flags = IORESOURCE_IRQ,
- }
- };
-
- if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
- num_ports = 2;
- else
- num_ports = 1;
-
- for (port = 0; port < num_ports; port++) {
- octeon_i2c_data[port].sys_freq = octeon_get_io_clock_rate();
- /*FIXME: should be examined. At the moment is set for 100Khz */
- octeon_i2c_data[port].i2c_freq = 100000;
-
- pd = platform_device_alloc("i2c-octeon", port);
- if (!pd) {
- ret = -ENOMEM;
- goto out;
- }
-
- pd->dev.platform_data = octeon_i2c_data + port;
-
- i2c_resources[0].start =
- OCTEON_I2C_IO_BASE + (port * OCTEON_I2C_IO_UNIT_OFFSET);
- i2c_resources[0].end = i2c_resources[0].start + 0x1f;
- switch (port) {
- case 0:
- i2c_resources[1].start = OCTEON_IRQ_TWSI;
- i2c_resources[1].end = OCTEON_IRQ_TWSI;
- break;
- case 1:
- i2c_resources[1].start = OCTEON_IRQ_TWSI2;
- i2c_resources[1].end = OCTEON_IRQ_TWSI2;
- break;
- default:
- BUG();
- }
-
- ret = platform_device_add_resources(pd,
- i2c_resources,
- ARRAY_SIZE(i2c_resources));
- if (ret)
- goto fail;
-
- ret = platform_device_add(pd);
- if (ret)
- goto fail;
- }
- return ret;
-fail:
- platform_device_put(pd);
-out:
- return ret;
-}
-device_initcall(octeon_i2c_device_init);
-
/* Octeon SMI/MDIO interface. */
static int __init octeon_mdiobus_device_init(void)
{
diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h
index f72f768..1e2486e 100644
--- a/arch/mips/include/asm/octeon/octeon.h
+++ b/arch/mips/include/asm/octeon/octeon.h
@@ -215,11 +215,6 @@ struct octeon_cf_data {
int dma_engine; /* -1 for no DMA */
};
-struct octeon_i2c_data {
- unsigned int sys_freq;
- unsigned int i2c_freq;
-};
-
extern void octeon_write_lcd(const char *s);
extern void octeon_check_cpu_bist(void);
extern int octeon_get_boot_debug_flag(void);
diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
index 56dbe54..cb34725 100644
--- a/drivers/i2c/busses/i2c-octeon.c
+++ b/drivers/i2c/busses/i2c-octeon.c
@@ -2,7 +2,7 @@
* (C) Copyright 2009-2010
* Nokia Siemens Networks, michael.lawnick.ext@nsn.com
*
- * Portions Copyright (C) 2010 Cavium Networks, Inc.
+ * Portions Copyright (C) 2010, 2011 Cavium Networks, Inc.
*
* This is a driver for the i2c adapter in Cavium Networks' OCTEON processors.
*
@@ -11,17 +11,18 @@
* warranty of any kind, whether express or implied.
*/
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/of_i2c.h>
+#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/init.h>
-
-#include <linux/io.h>
#include <linux/i2c.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/of.h>
#include <asm/octeon/octeon.h>
@@ -121,10 +122,8 @@ static u8 octeon_i2c_read_sw(struct octeon_i2c *i2c, u64 eop_reg)
*/
static void octeon_i2c_write_int(struct octeon_i2c *i2c, u64 data)
{
- u64 tmp;
-
__raw_writeq(data, i2c->twsi_base + TWSI_INT);
- tmp = __raw_readq(i2c->twsi_base + TWSI_INT);
+ __raw_readq(i2c->twsi_base + TWSI_INT);
}
/**
@@ -515,22 +514,22 @@ static int __devinit octeon_i2c_probe(struct platform_device *pdev)
{
int irq, result = 0;
struct octeon_i2c *i2c;
- struct octeon_i2c_data *i2c_data;
struct resource *res_mem;
+ const __be32 *data;
+ int len;
/* All adaptors have an irq. */
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
- i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
+ i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
if (!i2c) {
dev_err(&pdev->dev, "kzalloc failed\n");
result = -ENOMEM;
goto out;
}
i2c->dev = &pdev->dev;
- i2c_data = pdev->dev.platform_data;
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -539,19 +538,22 @@ static int __devinit octeon_i2c_probe(struct platform_device *pdev)
result = -ENXIO;
goto fail_region;
}
+ i2c->twsi_phys = res_mem->start;
+ i2c->regsize = resource_size(res_mem);
- if (i2c_data == NULL) {
- dev_err(i2c->dev, "no I2C frequency data\n");
+ data = of_get_property(pdev->dev.of_node, "clock-rate", &len);
+ if (data && len == sizeof(*data)) {
+ i2c->twsi_freq = be32_to_cpup(data);
+ } else {
+ dev_err(i2c->dev, "no I2C 'clock-rate' property\n");
result = -ENXIO;
goto fail_region;
}
- i2c->twsi_phys = res_mem->start;
- i2c->regsize = resource_size(res_mem);
- i2c->twsi_freq = i2c_data->i2c_freq;
- i2c->sys_freq = i2c_data->sys_freq;
+ i2c->sys_freq = octeon_get_io_clock_rate();
- if (!request_mem_region(i2c->twsi_phys, i2c->regsize, res_mem->name)) {
+ if (!devm_request_mem_region(&pdev->dev, i2c->twsi_phys, i2c->regsize,
+ res_mem->name)) {
dev_err(i2c->dev, "request_mem_region failed\n");
goto fail_region;
}
@@ -581,28 +583,31 @@ static int __devinit octeon_i2c_probe(struct platform_device *pdev)
i2c->adap = octeon_i2c_ops;
i2c->adap.dev.parent = &pdev->dev;
- i2c->adap.nr = pdev->id >= 0 ? pdev->id : 0;
+ i2c->adap.dev.of_node = pdev->dev.of_node;
i2c_set_adapdata(&i2c->adap, i2c);
platform_set_drvdata(pdev, i2c);
- result = i2c_add_numbered_adapter(&i2c->adap);
+ result = i2c_add_adapter(&i2c->adap);
if (result < 0) {
dev_err(i2c->dev, "failed to add adapter\n");
goto fail_add;
}
-
dev_info(i2c->dev, "version %s\n", DRV_VERSION);
- return result;
+ of_i2c_register_devices(&i2c->adap);
+
+ return 0;
fail_add:
platform_set_drvdata(pdev, NULL);
free_irq(i2c->irq, i2c);
fail_irq:
iounmap(i2c->twsi_base);
- release_mem_region(i2c->twsi_phys, i2c->regsize);
+
+ devm_release_mem_region(&pdev->dev, i2c->twsi_phys, i2c->regsize);
fail_region:
- kfree(i2c);
+
+ devm_kfree(&pdev->dev, i2c);
out:
return result;
};
@@ -615,17 +620,26 @@ static int __devexit octeon_i2c_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
free_irq(i2c->irq, i2c);
iounmap(i2c->twsi_base);
- release_mem_region(i2c->twsi_phys, i2c->regsize);
- kfree(i2c);
+ devm_release_mem_region(&pdev->dev, i2c->twsi_phys, i2c->regsize);
+ devm_kfree(&pdev->dev, i2c);
return 0;
};
+static struct of_device_id octeon_i2c_match[] = {
+ {
+ .compatible = "cavium,octeon-3860-twsi",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, octeon_i2c_match);
+
static struct platform_driver octeon_i2c_driver = {
.probe = octeon_i2c_probe,
.remove = __devexit_p(octeon_i2c_remove),
.driver = {
.owner = THIS_MODULE,
.name = DRV_NAME,
+ .of_match_table = octeon_i2c_match,
},
};
@@ -646,7 +660,6 @@ MODULE_AUTHOR("Michael Lawnick <michael.lawnick.ext@nsn.com>");
MODULE_DESCRIPTION("I2C-Bus adapter for Cavium OCTEON processors");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
-MODULE_ALIAS("platform:" DRV_NAME);
module_init(octeon_i2c_init);
module_exit(octeon_i2c_exit);
--
1.7.2.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [RFC PATCH v2 10/12] netdev: mdio-octeon.c: Convert to use device tree.
2011-03-04 19:42 ` David Daney
@ 2011-03-04 19:42 ` David Daney
-1 siblings, 0 replies; 40+ messages in thread
From: David Daney @ 2011-03-04 19:42 UTC (permalink / raw)
To: linux-mips-6z/3iImG2C8G8FEW9MqTrA, ralf-6z/3iImG2C8G8FEW9MqTrA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
grant.likely-s3s/WqlpOiPyB63q8FvJNQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: netdev-u79uwXL29TY76Z2rM5mHXA, David Daney, David S. Miller
Get the MDIO bus controller addresses from the device tree.
Signed-off-by: David Daney <ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8@public.gmane.org>
Cc: "David S. Miller" <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
Cc: netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
---
arch/mips/cavium-octeon/octeon-platform.c | 30 ---------
drivers/net/phy/mdio-octeon.c | 92 +++++++++++++++++++---------
2 files changed, 62 insertions(+), 60 deletions(-)
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
index 0533351..ce471bd 100644
--- a/arch/mips/cavium-octeon/octeon-platform.c
+++ b/arch/mips/cavium-octeon/octeon-platform.c
@@ -168,36 +168,6 @@ out:
}
device_initcall(octeon_rng_device_init);
-/* Octeon SMI/MDIO interface. */
-static int __init octeon_mdiobus_device_init(void)
-{
- struct platform_device *pd;
- int ret = 0;
-
- if (octeon_is_simulation())
- return 0; /* No mdio in the simulator. */
-
- /* The bus number is the platform_device id. */
- pd = platform_device_alloc("mdio-octeon", 0);
- if (!pd) {
- ret = -ENOMEM;
- goto out;
- }
-
- ret = platform_device_add(pd);
- if (ret)
- goto fail;
-
- return ret;
-fail:
- platform_device_put(pd);
-
-out:
- return ret;
-
-}
-device_initcall(octeon_mdiobus_device_init);
-
/* Octeon mgmt port Ethernet interface. */
static int __init octeon_mgmt_device_init(void)
{
diff --git a/drivers/net/phy/mdio-octeon.c b/drivers/net/phy/mdio-octeon.c
index bd12ba9..dd33023 100644
--- a/drivers/net/phy/mdio-octeon.c
+++ b/drivers/net/phy/mdio-octeon.c
@@ -3,13 +3,15 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2009 Cavium Networks
+ * Copyright (C) 2009, 2010, 2011 Cavium Networks
*/
-#include <linux/gfp.h>
-#include <linux/init.h>
-#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/of_mdio.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/gfp.h>
#include <linux/phy.h>
#include <asm/octeon/octeon.h>
@@ -18,9 +20,17 @@
#define DRV_VERSION "1.0"
#define DRV_DESCRIPTION "Cavium Networks Octeon SMI/MDIO driver"
+#define SMI_CMD 0x0
+#define SMI_WR_DAT 0x8
+#define SMI_RD_DAT 0x10
+#define SMI_CLK 0x18
+#define SMI_EN 0x20
+
struct octeon_mdiobus {
struct mii_bus *mii_bus;
- int unit;
+ u64 register_base;
+ resource_size_t mdio_phys;
+ resource_size_t regsize;
int phy_irq[PHY_MAX_ADDR];
};
@@ -35,15 +45,15 @@ static int octeon_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum)
smi_cmd.s.phy_op = 1; /* MDIO_CLAUSE_22_READ */
smi_cmd.s.phy_adr = phy_id;
smi_cmd.s.reg_adr = regnum;
- cvmx_write_csr(CVMX_SMIX_CMD(p->unit), smi_cmd.u64);
+ cvmx_write_csr(p->register_base + SMI_CMD, smi_cmd.u64);
do {
/*
* Wait 1000 clocks so we don't saturate the RSL bus
* doing reads.
*/
- cvmx_wait(1000);
- smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(p->unit));
+ __delay(1000);
+ smi_rd.u64 = cvmx_read_csr(p->register_base + SMI_RD_DAT);
} while (smi_rd.s.pending && --timeout);
if (smi_rd.s.val)
@@ -62,21 +72,21 @@ static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id,
smi_wr.u64 = 0;
smi_wr.s.dat = val;
- cvmx_write_csr(CVMX_SMIX_WR_DAT(p->unit), smi_wr.u64);
+ cvmx_write_csr(p->register_base + SMI_WR_DAT, smi_wr.u64);
smi_cmd.u64 = 0;
smi_cmd.s.phy_op = 0; /* MDIO_CLAUSE_22_WRITE */
smi_cmd.s.phy_adr = phy_id;
smi_cmd.s.reg_adr = regnum;
- cvmx_write_csr(CVMX_SMIX_CMD(p->unit), smi_cmd.u64);
+ cvmx_write_csr(p->register_base + SMI_CMD, smi_cmd.u64);
do {
/*
* Wait 1000 clocks so we don't saturate the RSL bus
* doing reads.
*/
- cvmx_wait(1000);
- smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(p->unit));
+ __delay(1000);
+ smi_wr.u64 = cvmx_read_csr(p->register_base + SMI_WR_DAT);
} while (smi_wr.s.pending && --timeout);
if (timeout <= 0)
@@ -88,8 +98,8 @@ static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id,
static int __devinit octeon_mdiobus_probe(struct platform_device *pdev)
{
struct octeon_mdiobus *bus;
+ struct resource *res_mem;
union cvmx_smix_en smi_en;
- int i;
int err = -ENOENT;
bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
@@ -97,28 +107,36 @@ static int __devinit octeon_mdiobus_probe(struct platform_device *pdev)
return -ENOMEM;
/* The platform_device id is our unit number. */
- bus->unit = pdev->id;
+ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (res_mem == NULL) {
+ dev_err(&pdev->dev, "found no memory resource\n");
+ err = -ENXIO;
+ goto fail_region;
+ }
+ bus->mdio_phys = res_mem->start;
+ bus->regsize = resource_size(res_mem);
+ if (!devm_request_mem_region(&pdev->dev, bus->mdio_phys, bus->regsize,
+ res_mem->name)) {
+ dev_err(&pdev->dev, "request_mem_region failed\n");
+ goto fail_region;
+ }
+ bus->register_base = (u64)ioremap(bus->mdio_phys, bus->regsize);
bus->mii_bus = mdiobus_alloc();
if (!bus->mii_bus)
- goto err;
+ goto fail_mdio_alloc;
smi_en.u64 = 0;
smi_en.s.en = 1;
- cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64);
+ cvmx_write_csr(bus->register_base + SMI_EN, smi_en.u64);
- /*
- * Standard Octeon evaluation boards don't support phy
- * interrupts, we need to poll.
- */
- for (i = 0; i < PHY_MAX_ADDR; i++)
- bus->phy_irq[i] = PHY_POLL;
bus->mii_bus->priv = bus;
bus->mii_bus->irq = bus->phy_irq;
bus->mii_bus->name = "mdio-octeon";
- snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%x", bus->unit);
+ snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%llx", bus->register_base);
bus->mii_bus->parent = &pdev->dev;
bus->mii_bus->read = octeon_mdiobus_read;
@@ -126,20 +144,23 @@ static int __devinit octeon_mdiobus_probe(struct platform_device *pdev)
dev_set_drvdata(&pdev->dev, bus);
- err = mdiobus_register(bus->mii_bus);
+ err = of_mdiobus_register(bus->mii_bus, pdev->dev.of_node);
if (err)
- goto err_register;
+ goto fail_register;
dev_info(&pdev->dev, "Version " DRV_VERSION "\n");
return 0;
-err_register:
+fail_register:
mdiobus_free(bus->mii_bus);
-err:
- devm_kfree(&pdev->dev, bus);
+fail_mdio_alloc:
+ devm_release_mem_region(&pdev->dev, bus->mdio_phys, bus->regsize);
+
+fail_region:
smi_en.u64 = 0;
- cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64);
+ cvmx_write_csr(bus->register_base + SMI_EN, smi_en.u64);
+ devm_kfree(&pdev->dev, bus);
return err;
}
@@ -152,15 +173,26 @@ static int __devexit octeon_mdiobus_remove(struct platform_device *pdev)
mdiobus_unregister(bus->mii_bus);
mdiobus_free(bus->mii_bus);
+ devm_release_mem_region(&pdev->dev, bus->mdio_phys, bus->regsize);
smi_en.u64 = 0;
- cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64);
+ cvmx_write_csr(bus->register_base + SMI_EN, smi_en.u64);
+ devm_kfree(&pdev->dev, bus);
return 0;
}
+static struct of_device_id octeon_mdiobus_match[] = {
+ {
+ .compatible = "cavium,octeon-3860-mdio",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, octeon_mdiobus_match);
+
static struct platform_driver octeon_mdiobus_driver = {
.driver = {
.name = "mdio-octeon",
.owner = THIS_MODULE,
+ .of_match_table = octeon_mdiobus_match,
},
.probe = octeon_mdiobus_probe,
.remove = __devexit_p(octeon_mdiobus_remove),
--
1.7.2.3
^ permalink raw reply related [flat|nested] 40+ messages in thread* [RFC PATCH v2 10/12] netdev: mdio-octeon.c: Convert to use device tree.
@ 2011-03-04 19:42 ` David Daney
0 siblings, 0 replies; 40+ messages in thread
From: David Daney @ 2011-03-04 19:42 UTC (permalink / raw)
To: linux-mips, ralf, devicetree-discuss, grant.likely, linux-kernel
Cc: David Daney, David S. Miller, netdev
Get the MDIO bus controller addresses from the device tree.
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: netdev@vger.kernel.org
---
arch/mips/cavium-octeon/octeon-platform.c | 30 ---------
drivers/net/phy/mdio-octeon.c | 92 +++++++++++++++++++---------
2 files changed, 62 insertions(+), 60 deletions(-)
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
index 0533351..ce471bd 100644
--- a/arch/mips/cavium-octeon/octeon-platform.c
+++ b/arch/mips/cavium-octeon/octeon-platform.c
@@ -168,36 +168,6 @@ out:
}
device_initcall(octeon_rng_device_init);
-/* Octeon SMI/MDIO interface. */
-static int __init octeon_mdiobus_device_init(void)
-{
- struct platform_device *pd;
- int ret = 0;
-
- if (octeon_is_simulation())
- return 0; /* No mdio in the simulator. */
-
- /* The bus number is the platform_device id. */
- pd = platform_device_alloc("mdio-octeon", 0);
- if (!pd) {
- ret = -ENOMEM;
- goto out;
- }
-
- ret = platform_device_add(pd);
- if (ret)
- goto fail;
-
- return ret;
-fail:
- platform_device_put(pd);
-
-out:
- return ret;
-
-}
-device_initcall(octeon_mdiobus_device_init);
-
/* Octeon mgmt port Ethernet interface. */
static int __init octeon_mgmt_device_init(void)
{
diff --git a/drivers/net/phy/mdio-octeon.c b/drivers/net/phy/mdio-octeon.c
index bd12ba9..dd33023 100644
--- a/drivers/net/phy/mdio-octeon.c
+++ b/drivers/net/phy/mdio-octeon.c
@@ -3,13 +3,15 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2009 Cavium Networks
+ * Copyright (C) 2009, 2010, 2011 Cavium Networks
*/
-#include <linux/gfp.h>
-#include <linux/init.h>
-#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/of_mdio.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/gfp.h>
#include <linux/phy.h>
#include <asm/octeon/octeon.h>
@@ -18,9 +20,17 @@
#define DRV_VERSION "1.0"
#define DRV_DESCRIPTION "Cavium Networks Octeon SMI/MDIO driver"
+#define SMI_CMD 0x0
+#define SMI_WR_DAT 0x8
+#define SMI_RD_DAT 0x10
+#define SMI_CLK 0x18
+#define SMI_EN 0x20
+
struct octeon_mdiobus {
struct mii_bus *mii_bus;
- int unit;
+ u64 register_base;
+ resource_size_t mdio_phys;
+ resource_size_t regsize;
int phy_irq[PHY_MAX_ADDR];
};
@@ -35,15 +45,15 @@ static int octeon_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum)
smi_cmd.s.phy_op = 1; /* MDIO_CLAUSE_22_READ */
smi_cmd.s.phy_adr = phy_id;
smi_cmd.s.reg_adr = regnum;
- cvmx_write_csr(CVMX_SMIX_CMD(p->unit), smi_cmd.u64);
+ cvmx_write_csr(p->register_base + SMI_CMD, smi_cmd.u64);
do {
/*
* Wait 1000 clocks so we don't saturate the RSL bus
* doing reads.
*/
- cvmx_wait(1000);
- smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(p->unit));
+ __delay(1000);
+ smi_rd.u64 = cvmx_read_csr(p->register_base + SMI_RD_DAT);
} while (smi_rd.s.pending && --timeout);
if (smi_rd.s.val)
@@ -62,21 +72,21 @@ static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id,
smi_wr.u64 = 0;
smi_wr.s.dat = val;
- cvmx_write_csr(CVMX_SMIX_WR_DAT(p->unit), smi_wr.u64);
+ cvmx_write_csr(p->register_base + SMI_WR_DAT, smi_wr.u64);
smi_cmd.u64 = 0;
smi_cmd.s.phy_op = 0; /* MDIO_CLAUSE_22_WRITE */
smi_cmd.s.phy_adr = phy_id;
smi_cmd.s.reg_adr = regnum;
- cvmx_write_csr(CVMX_SMIX_CMD(p->unit), smi_cmd.u64);
+ cvmx_write_csr(p->register_base + SMI_CMD, smi_cmd.u64);
do {
/*
* Wait 1000 clocks so we don't saturate the RSL bus
* doing reads.
*/
- cvmx_wait(1000);
- smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(p->unit));
+ __delay(1000);
+ smi_wr.u64 = cvmx_read_csr(p->register_base + SMI_WR_DAT);
} while (smi_wr.s.pending && --timeout);
if (timeout <= 0)
@@ -88,8 +98,8 @@ static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id,
static int __devinit octeon_mdiobus_probe(struct platform_device *pdev)
{
struct octeon_mdiobus *bus;
+ struct resource *res_mem;
union cvmx_smix_en smi_en;
- int i;
int err = -ENOENT;
bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
@@ -97,28 +107,36 @@ static int __devinit octeon_mdiobus_probe(struct platform_device *pdev)
return -ENOMEM;
/* The platform_device id is our unit number. */
- bus->unit = pdev->id;
+ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (res_mem == NULL) {
+ dev_err(&pdev->dev, "found no memory resource\n");
+ err = -ENXIO;
+ goto fail_region;
+ }
+ bus->mdio_phys = res_mem->start;
+ bus->regsize = resource_size(res_mem);
+ if (!devm_request_mem_region(&pdev->dev, bus->mdio_phys, bus->regsize,
+ res_mem->name)) {
+ dev_err(&pdev->dev, "request_mem_region failed\n");
+ goto fail_region;
+ }
+ bus->register_base = (u64)ioremap(bus->mdio_phys, bus->regsize);
bus->mii_bus = mdiobus_alloc();
if (!bus->mii_bus)
- goto err;
+ goto fail_mdio_alloc;
smi_en.u64 = 0;
smi_en.s.en = 1;
- cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64);
+ cvmx_write_csr(bus->register_base + SMI_EN, smi_en.u64);
- /*
- * Standard Octeon evaluation boards don't support phy
- * interrupts, we need to poll.
- */
- for (i = 0; i < PHY_MAX_ADDR; i++)
- bus->phy_irq[i] = PHY_POLL;
bus->mii_bus->priv = bus;
bus->mii_bus->irq = bus->phy_irq;
bus->mii_bus->name = "mdio-octeon";
- snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%x", bus->unit);
+ snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%llx", bus->register_base);
bus->mii_bus->parent = &pdev->dev;
bus->mii_bus->read = octeon_mdiobus_read;
@@ -126,20 +144,23 @@ static int __devinit octeon_mdiobus_probe(struct platform_device *pdev)
dev_set_drvdata(&pdev->dev, bus);
- err = mdiobus_register(bus->mii_bus);
+ err = of_mdiobus_register(bus->mii_bus, pdev->dev.of_node);
if (err)
- goto err_register;
+ goto fail_register;
dev_info(&pdev->dev, "Version " DRV_VERSION "\n");
return 0;
-err_register:
+fail_register:
mdiobus_free(bus->mii_bus);
-err:
- devm_kfree(&pdev->dev, bus);
+fail_mdio_alloc:
+ devm_release_mem_region(&pdev->dev, bus->mdio_phys, bus->regsize);
+
+fail_region:
smi_en.u64 = 0;
- cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64);
+ cvmx_write_csr(bus->register_base + SMI_EN, smi_en.u64);
+ devm_kfree(&pdev->dev, bus);
return err;
}
@@ -152,15 +173,26 @@ static int __devexit octeon_mdiobus_remove(struct platform_device *pdev)
mdiobus_unregister(bus->mii_bus);
mdiobus_free(bus->mii_bus);
+ devm_release_mem_region(&pdev->dev, bus->mdio_phys, bus->regsize);
smi_en.u64 = 0;
- cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64);
+ cvmx_write_csr(bus->register_base + SMI_EN, smi_en.u64);
+ devm_kfree(&pdev->dev, bus);
return 0;
}
+static struct of_device_id octeon_mdiobus_match[] = {
+ {
+ .compatible = "cavium,octeon-3860-mdio",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, octeon_mdiobus_match);
+
static struct platform_driver octeon_mdiobus_driver = {
.driver = {
.name = "mdio-octeon",
.owner = THIS_MODULE,
+ .of_match_table = octeon_mdiobus_match,
},
.probe = octeon_mdiobus_probe,
.remove = __devexit_p(octeon_mdiobus_remove),
--
1.7.2.3
^ permalink raw reply related [flat|nested] 40+ messages in thread* Re: [RFC PATCH v2 10/12] netdev: mdio-octeon.c: Convert to use device tree.
2011-03-04 19:42 ` David Daney
(?)
@ 2011-03-04 21:10 ` David Miller
-1 siblings, 0 replies; 40+ messages in thread
From: David Miller @ 2011-03-04 21:10 UTC (permalink / raw)
To: ddaney
Cc: linux-mips, ralf, devicetree-discuss, grant.likely, linux-kernel,
netdev
From: David Daney <ddaney@caviumnetworks.com>
Date: Fri, 4 Mar 2011 11:42:22 -0800
> Get the MDIO bus controller addresses from the device tree.
>
> Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Acked-by: David S. Miller <davem@davemloft.net>
^ permalink raw reply [flat|nested] 40+ messages in thread
* [RFC PATCH v2 11/12] netdev: octeon_mgmt: Convert to use device tree.
2011-03-04 19:42 ` David Daney
@ 2011-03-04 19:42 ` David Daney
-1 siblings, 0 replies; 40+ messages in thread
From: David Daney @ 2011-03-04 19:42 UTC (permalink / raw)
To: linux-mips-6z/3iImG2C8G8FEW9MqTrA, ralf-6z/3iImG2C8G8FEW9MqTrA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
grant.likely-s3s/WqlpOiPyB63q8FvJNQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: netdev-u79uwXL29TY76Z2rM5mHXA, David Daney, David S. Miller
The device tree will supply the register bank base addresses, make
register addressing relative to those. PHY connection is now
described by the device tree.
Signed-off-by: David Daney <ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8@public.gmane.org>
Cc: "David S. Miller" <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
Cc: netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
---
arch/mips/cavium-octeon/octeon-platform.c | 62 ------
drivers/net/octeon/octeon_mgmt.c | 321 +++++++++++++++++++----------
2 files changed, 217 insertions(+), 166 deletions(-)
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
index ce471bd..104713c 100644
--- a/arch/mips/cavium-octeon/octeon-platform.c
+++ b/arch/mips/cavium-octeon/octeon-platform.c
@@ -168,68 +168,6 @@ out:
}
device_initcall(octeon_rng_device_init);
-/* Octeon mgmt port Ethernet interface. */
-static int __init octeon_mgmt_device_init(void)
-{
- struct platform_device *pd;
- int ret = 0;
- int port, num_ports;
-
- struct resource mgmt_port_resource = {
- .flags = IORESOURCE_IRQ,
- .start = -1,
- .end = -1
- };
-
- if (!OCTEON_IS_MODEL(OCTEON_CN56XX) && !OCTEON_IS_MODEL(OCTEON_CN52XX))
- return 0;
-
- if (OCTEON_IS_MODEL(OCTEON_CN56XX))
- num_ports = 1;
- else
- num_ports = 2;
-
- for (port = 0; port < num_ports; port++) {
- pd = platform_device_alloc("octeon_mgmt", port);
- if (!pd) {
- ret = -ENOMEM;
- goto out;
- }
- /* No DMA restrictions */
- pd->dev.coherent_dma_mask = DMA_BIT_MASK(64);
- pd->dev.dma_mask = &pd->dev.coherent_dma_mask;
-
- switch (port) {
- case 0:
- mgmt_port_resource.start = OCTEON_IRQ_MII0;
- break;
- case 1:
- mgmt_port_resource.start = OCTEON_IRQ_MII1;
- break;
- default:
- BUG();
- }
- mgmt_port_resource.end = mgmt_port_resource.start;
-
- ret = platform_device_add_resources(pd, &mgmt_port_resource, 1);
-
- if (ret)
- goto fail;
-
- ret = platform_device_add(pd);
- if (ret)
- goto fail;
- }
- return ret;
-fail:
- platform_device_put(pd);
-
-out:
- return ret;
-
-}
-device_initcall(octeon_mgmt_device_init);
-
#ifdef CONFIG_USB
static int __init octeon_ehci_device_init(void)
diff --git a/drivers/net/octeon/octeon_mgmt.c b/drivers/net/octeon/octeon_mgmt.c
index b264f0f..17be326 100644
--- a/drivers/net/octeon/octeon_mgmt.c
+++ b/drivers/net/octeon/octeon_mgmt.c
@@ -6,16 +6,18 @@
* Copyright (C) 2009 Cavium Networks
*/
-#include <linux/capability.h>
-#include <linux/dma-mapping.h>
-#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/netdevice.h>
+#include <linux/dma-mapping.h>
#include <linux/etherdevice.h>
+#include <linux/capability.h>
+#include <linux/netdevice.h>
+#include <linux/spinlock.h>
#include <linux/if_vlan.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
+#include <linux/init.h>
#include <linux/slab.h>
#include <linux/phy.h>
-#include <linux/spinlock.h>
#include <asm/octeon/octeon.h>
#include <asm/octeon/cvmx-mixx-defs.h>
@@ -55,8 +57,56 @@ union mgmt_port_ring_entry {
} s;
};
+#define MIX_ORING1 0x0
+#define MIX_ORING2 0x8
+#define MIX_IRING1 0x10
+#define MIX_IRING2 0x18
+#define MIX_CTL 0x20
+#define MIX_IRHWM 0x28
+#define MIX_IRCNT 0x30
+#define MIX_ORHWM 0x38
+#define MIX_ORCNT 0x40
+#define MIX_ISR 0x48
+#define MIX_INTENA 0x50
+#define MIX_REMCNT 0x58
+#define MIX_BIST 0x78
+
+#define AGL_GMX_PRT_CFG 0x10
+#define AGL_GMX_RX_FRM_CTL 0x18
+#define AGL_GMX_RX_FRM_MAX 0x30
+#define AGL_GMX_RX_JABBER 0x38
+#define AGL_GMX_RX_STATS_CTL 0x50
+
+#define AGL_GMX_RX_STATS_PKTS_DRP 0xb0
+#define AGL_GMX_RX_STATS_OCTS_DRP 0xb8
+#define AGL_GMX_RX_STATS_PKTS_BAD 0xc0
+
+#define AGL_GMX_RX_ADR_CTL 0x100
+#define AGL_GMX_RX_ADR_CAM_EN 0x108
+#define AGL_GMX_RX_ADR_CAM0 0x180
+#define AGL_GMX_RX_ADR_CAM1 0x188
+#define AGL_GMX_RX_ADR_CAM2 0x190
+#define AGL_GMX_RX_ADR_CAM3 0x198
+#define AGL_GMX_RX_ADR_CAM4 0x1a0
+#define AGL_GMX_RX_ADR_CAM5 0x1a8
+
+#define AGL_GMX_TX_STATS_CTL 0x268
+#define AGL_GMX_TX_CTL 0x270
+#define AGL_GMX_TX_STAT0 0x280
+#define AGL_GMX_TX_STAT1 0x288
+#define AGL_GMX_TX_STAT2 0x290
+#define AGL_GMX_TX_STAT3 0x298
+#define AGL_GMX_TX_STAT4 0x2a0
+#define AGL_GMX_TX_STAT5 0x2a8
+#define AGL_GMX_TX_STAT6 0x2b0
+#define AGL_GMX_TX_STAT7 0x2b8
+#define AGL_GMX_TX_STAT8 0x2c0
+#define AGL_GMX_TX_STAT9 0x2c8
+
struct octeon_mgmt {
struct net_device *netdev;
+ u64 mix;
+ u64 agl;
int port;
int irq;
u64 *tx_ring;
@@ -82,31 +132,34 @@ struct octeon_mgmt {
struct napi_struct napi;
struct tasklet_struct tx_clean_tasklet;
struct phy_device *phydev;
+ struct device_node *phy_np;
+ resource_size_t mix_phys;
+ resource_size_t mix_size;
+ resource_size_t agl_phys;
+ resource_size_t agl_size;
};
static void octeon_mgmt_set_rx_irq(struct octeon_mgmt *p, int enable)
{
- int port = p->port;
union cvmx_mixx_intena mix_intena;
unsigned long flags;
spin_lock_irqsave(&p->lock, flags);
- mix_intena.u64 = cvmx_read_csr(CVMX_MIXX_INTENA(port));
+ mix_intena.u64 = cvmx_read_csr(p->mix + MIX_INTENA);
mix_intena.s.ithena = enable ? 1 : 0;
- cvmx_write_csr(CVMX_MIXX_INTENA(port), mix_intena.u64);
+ cvmx_write_csr(p->mix + MIX_INTENA, mix_intena.u64);
spin_unlock_irqrestore(&p->lock, flags);
}
static void octeon_mgmt_set_tx_irq(struct octeon_mgmt *p, int enable)
{
- int port = p->port;
union cvmx_mixx_intena mix_intena;
unsigned long flags;
spin_lock_irqsave(&p->lock, flags);
- mix_intena.u64 = cvmx_read_csr(CVMX_MIXX_INTENA(port));
+ mix_intena.u64 = cvmx_read_csr(p->mix + MIX_INTENA);
mix_intena.s.othena = enable ? 1 : 0;
- cvmx_write_csr(CVMX_MIXX_INTENA(port), mix_intena.u64);
+ cvmx_write_csr(p->mix + MIX_INTENA, mix_intena.u64);
spin_unlock_irqrestore(&p->lock, flags);
}
@@ -143,7 +196,6 @@ static unsigned int ring_size_to_bytes(unsigned int ring_size)
static void octeon_mgmt_rx_fill_ring(struct net_device *netdev)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
while (p->rx_current_fill < ring_max_fill(OCTEON_MGMT_RX_RING_SIZE)) {
unsigned int size;
@@ -174,24 +226,23 @@ static void octeon_mgmt_rx_fill_ring(struct net_device *netdev)
(p->rx_next_fill + 1) % OCTEON_MGMT_RX_RING_SIZE;
p->rx_current_fill++;
/* Ring the bell. */
- cvmx_write_csr(CVMX_MIXX_IRING2(port), 1);
+ cvmx_write_csr(p->mix + MIX_IRING2, 1);
}
}
static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p)
{
- int port = p->port;
union cvmx_mixx_orcnt mix_orcnt;
union mgmt_port_ring_entry re;
struct sk_buff *skb;
int cleaned = 0;
unsigned long flags;
- mix_orcnt.u64 = cvmx_read_csr(CVMX_MIXX_ORCNT(port));
+ mix_orcnt.u64 = cvmx_read_csr(p->mix + MIX_ORCNT);
while (mix_orcnt.s.orcnt) {
spin_lock_irqsave(&p->tx_list.lock, flags);
- mix_orcnt.u64 = cvmx_read_csr(CVMX_MIXX_ORCNT(port));
+ mix_orcnt.u64 = cvmx_read_csr(p->mix + MIX_ORCNT);
if (mix_orcnt.s.orcnt == 0) {
spin_unlock_irqrestore(&p->tx_list.lock, flags);
@@ -211,7 +262,7 @@ static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p)
mix_orcnt.s.orcnt = 1;
/* Acknowledge to hardware that we have the buffer. */
- cvmx_write_csr(CVMX_MIXX_ORCNT(port), mix_orcnt.u64);
+ cvmx_write_csr(p->mix + MIX_ORCNT, mix_orcnt.u64);
p->tx_current_fill--;
spin_unlock_irqrestore(&p->tx_list.lock, flags);
@@ -221,7 +272,7 @@ static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p)
dev_kfree_skb_any(skb);
cleaned++;
- mix_orcnt.u64 = cvmx_read_csr(CVMX_MIXX_ORCNT(port));
+ mix_orcnt.u64 = cvmx_read_csr(p->mix + MIX_ORCNT);
}
if (cleaned && netif_queue_stopped(p->netdev))
@@ -238,13 +289,12 @@ static void octeon_mgmt_clean_tx_tasklet(unsigned long arg)
static void octeon_mgmt_update_rx_stats(struct net_device *netdev)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
unsigned long flags;
u64 drop, bad;
/* These reads also clear the count registers. */
- drop = cvmx_read_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_DRP(port));
- bad = cvmx_read_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_BAD(port));
+ drop = cvmx_read_csr(p->agl + AGL_GMX_RX_STATS_PKTS_DRP);
+ bad = cvmx_read_csr(p->agl + AGL_GMX_RX_STATS_PKTS_BAD);
if (drop || bad) {
/* Do an atomic update. */
@@ -258,15 +308,14 @@ static void octeon_mgmt_update_rx_stats(struct net_device *netdev)
static void octeon_mgmt_update_tx_stats(struct net_device *netdev)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
unsigned long flags;
union cvmx_agl_gmx_txx_stat0 s0;
union cvmx_agl_gmx_txx_stat1 s1;
/* These reads also clear the count registers. */
- s0.u64 = cvmx_read_csr(CVMX_AGL_GMX_TXX_STAT0(port));
- s1.u64 = cvmx_read_csr(CVMX_AGL_GMX_TXX_STAT1(port));
+ s0.u64 = cvmx_read_csr(p->agl + AGL_GMX_TX_STAT0);
+ s1.u64 = cvmx_read_csr(p->agl + AGL_GMX_TX_STAT1);
if (s0.s.xsdef || s0.s.xscol || s1.s.scol || s1.s.mcol) {
/* Do an atomic update. */
@@ -305,7 +354,6 @@ static u64 octeon_mgmt_dequeue_rx_buffer(struct octeon_mgmt *p,
static int octeon_mgmt_receive_one(struct octeon_mgmt *p)
{
- int port = p->port;
struct net_device *netdev = p->netdev;
union cvmx_mixx_ircnt mix_ircnt;
union mgmt_port_ring_entry re;
@@ -378,18 +426,17 @@ done:
/* Tell the hardware we processed a packet. */
mix_ircnt.u64 = 0;
mix_ircnt.s.ircnt = 1;
- cvmx_write_csr(CVMX_MIXX_IRCNT(port), mix_ircnt.u64);
+ cvmx_write_csr(p->mix + MIX_IRCNT, mix_ircnt.u64);
return rc;
}
static int octeon_mgmt_receive_packets(struct octeon_mgmt *p, int budget)
{
- int port = p->port;
unsigned int work_done = 0;
union cvmx_mixx_ircnt mix_ircnt;
int rc;
- mix_ircnt.u64 = cvmx_read_csr(CVMX_MIXX_IRCNT(port));
+ mix_ircnt.u64 = cvmx_read_csr(p->mix + MIX_IRCNT);
while (work_done < budget && mix_ircnt.s.ircnt) {
rc = octeon_mgmt_receive_one(p);
@@ -397,7 +444,7 @@ static int octeon_mgmt_receive_packets(struct octeon_mgmt *p, int budget)
work_done++;
/* Check for more packets. */
- mix_ircnt.u64 = cvmx_read_csr(CVMX_MIXX_IRCNT(port));
+ mix_ircnt.u64 = cvmx_read_csr(p->mix + MIX_IRCNT);
}
octeon_mgmt_rx_fill_ring(p->netdev);
@@ -431,16 +478,16 @@ static void octeon_mgmt_reset_hw(struct octeon_mgmt *p)
union cvmx_agl_gmx_bist agl_gmx_bist;
mix_ctl.u64 = 0;
- cvmx_write_csr(CVMX_MIXX_CTL(p->port), mix_ctl.u64);
+ cvmx_write_csr(p->mix + MIX_CTL, mix_ctl.u64);
do {
- mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(p->port));
+ mix_ctl.u64 = cvmx_read_csr(p->mix + MIX_CTL);
} while (mix_ctl.s.busy);
mix_ctl.s.reset = 1;
- cvmx_write_csr(CVMX_MIXX_CTL(p->port), mix_ctl.u64);
- cvmx_read_csr(CVMX_MIXX_CTL(p->port));
+ cvmx_write_csr(p->mix + MIX_CTL, mix_ctl.u64);
+ cvmx_read_csr(p->mix + MIX_CTL);
cvmx_wait(64);
- mix_bist.u64 = cvmx_read_csr(CVMX_MIXX_BIST(p->port));
+ mix_bist.u64 = cvmx_read_csr(p->mix + MIX_BIST);
if (mix_bist.u64)
dev_warn(p->dev, "MIX failed BIST (0x%016llx)\n",
(unsigned long long)mix_bist.u64);
@@ -471,7 +518,6 @@ static void octeon_mgmt_cam_state_add(struct octeon_mgmt_cam_state *cs,
static void octeon_mgmt_set_rx_filtering(struct net_device *netdev)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
union cvmx_agl_gmx_rxx_adr_ctl adr_ctl;
union cvmx_agl_gmx_prtx_cfg agl_gmx_prtx;
unsigned long flags;
@@ -517,29 +563,29 @@ static void octeon_mgmt_set_rx_filtering(struct net_device *netdev)
spin_lock_irqsave(&p->lock, flags);
/* Disable packet I/O. */
- agl_gmx_prtx.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
+ agl_gmx_prtx.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
prev_packet_enable = agl_gmx_prtx.s.en;
agl_gmx_prtx.s.en = 0;
- cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_prtx.u64);
+ cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, agl_gmx_prtx.u64);
adr_ctl.u64 = 0;
adr_ctl.s.cam_mode = cam_mode;
adr_ctl.s.mcst = multicast_mode;
adr_ctl.s.bcst = 1; /* Allow broadcast */
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CTL(port), adr_ctl.u64);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CTL, adr_ctl.u64);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM0(port), cam_state.cam[0]);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM1(port), cam_state.cam[1]);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM2(port), cam_state.cam[2]);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM3(port), cam_state.cam[3]);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM4(port), cam_state.cam[4]);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM5(port), cam_state.cam[5]);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM_EN(port), cam_state.cam_mask);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM0, cam_state.cam[0]);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM1, cam_state.cam[1]);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM2, cam_state.cam[2]);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM3, cam_state.cam[3]);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM4, cam_state.cam[4]);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM5, cam_state.cam[5]);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM_EN, cam_state.cam_mask);
/* Restore packet I/O. */
agl_gmx_prtx.s.en = prev_packet_enable;
- cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_prtx.u64);
+ cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, agl_gmx_prtx.u64);
spin_unlock_irqrestore(&p->lock, flags);
}
@@ -561,7 +607,6 @@ static int octeon_mgmt_set_mac_address(struct net_device *netdev, void *addr)
static int octeon_mgmt_change_mtu(struct net_device *netdev, int new_mtu)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
int size_without_fcs = new_mtu + OCTEON_MGMT_RX_HEADROOM;
/*
@@ -577,8 +622,8 @@ static int octeon_mgmt_change_mtu(struct net_device *netdev, int new_mtu)
netdev->mtu = new_mtu;
- cvmx_write_csr(CVMX_AGL_GMX_RXX_FRM_MAX(port), size_without_fcs);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_JABBER(port),
+ cvmx_write_csr(p->agl + AGL_GMX_RX_FRM_MAX, size_without_fcs);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_JABBER,
(size_without_fcs + 7) & 0xfff8);
return 0;
@@ -588,14 +633,13 @@ static irqreturn_t octeon_mgmt_interrupt(int cpl, void *dev_id)
{
struct net_device *netdev = dev_id;
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
union cvmx_mixx_isr mixx_isr;
- mixx_isr.u64 = cvmx_read_csr(CVMX_MIXX_ISR(port));
+ mixx_isr.u64 = cvmx_read_csr(p->mix + MIX_ISR);
/* Clear any pending interrupts */
- cvmx_write_csr(CVMX_MIXX_ISR(port), mixx_isr.u64);
- cvmx_read_csr(CVMX_MIXX_ISR(port));
+ cvmx_write_csr(p->mix + MIX_ISR, mixx_isr.u64);
+ cvmx_read_csr(p->mix + MIX_ISR);
if (mixx_isr.s.irthresh) {
octeon_mgmt_disable_rx_irq(p);
@@ -626,7 +670,6 @@ static int octeon_mgmt_ioctl(struct net_device *netdev,
static void octeon_mgmt_adjust_link(struct net_device *netdev)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
union cvmx_agl_gmx_prtx_cfg prtx_cfg;
unsigned long flags;
int link_changed = 0;
@@ -637,11 +680,9 @@ static void octeon_mgmt_adjust_link(struct net_device *netdev)
link_changed = 1;
if (p->last_duplex != p->phydev->duplex) {
p->last_duplex = p->phydev->duplex;
- prtx_cfg.u64 =
- cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
+ prtx_cfg.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
prtx_cfg.s.duplex = p->phydev->duplex;
- cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port),
- prtx_cfg.u64);
+ cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, prtx_cfg.u64);
}
} else {
if (p->last_link)
@@ -667,18 +708,16 @@ static void octeon_mgmt_adjust_link(struct net_device *netdev)
static int octeon_mgmt_init_phy(struct net_device *netdev)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- char phy_id[20];
- if (octeon_is_simulation()) {
+ if (octeon_is_simulation() || p->phy_np == NULL) {
/* No PHYs in the simulator. */
netif_carrier_on(netdev);
return 0;
}
- snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "0", p->port);
-
- p->phydev = phy_connect(netdev, phy_id, octeon_mgmt_adjust_link, 0,
- PHY_INTERFACE_MODE_MII);
+ p->phydev = of_phy_connect(netdev, p->phy_np,
+ octeon_mgmt_adjust_link, 0,
+ PHY_INTERFACE_MODE_MII);
if (IS_ERR(p->phydev)) {
p->phydev = NULL;
@@ -734,14 +773,14 @@ static int octeon_mgmt_open(struct net_device *netdev)
octeon_mgmt_reset_hw(p);
- mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(port));
+ mix_ctl.u64 = cvmx_read_csr(p->mix + MIX_CTL);
/* Bring it out of reset if needed. */
if (mix_ctl.s.reset) {
mix_ctl.s.reset = 0;
- cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64);
+ cvmx_write_csr(p->mix + MIX_CTL, mix_ctl.u64);
do {
- mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(port));
+ mix_ctl.u64 = cvmx_read_csr(p->mix + MIX_CTL);
} while (mix_ctl.s.reset);
}
@@ -752,17 +791,17 @@ static int octeon_mgmt_open(struct net_device *netdev)
oring1.u64 = 0;
oring1.s.obase = p->tx_ring_handle >> 3;
oring1.s.osize = OCTEON_MGMT_TX_RING_SIZE;
- cvmx_write_csr(CVMX_MIXX_ORING1(port), oring1.u64);
+ cvmx_write_csr(p->mix + MIX_ORING1, oring1.u64);
iring1.u64 = 0;
iring1.s.ibase = p->rx_ring_handle >> 3;
iring1.s.isize = OCTEON_MGMT_RX_RING_SIZE;
- cvmx_write_csr(CVMX_MIXX_IRING1(port), iring1.u64);
+ cvmx_write_csr(p->mix + MIX_IRING1, iring1.u64);
/* Disable packet I/O. */
- prtx_cfg.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
+ prtx_cfg.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
prtx_cfg.s.en = 0;
- cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), prtx_cfg.u64);
+ cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, prtx_cfg.u64);
memcpy(sa.sa_data, netdev->dev_addr, ETH_ALEN);
octeon_mgmt_set_mac_address(netdev, &sa);
@@ -779,7 +818,7 @@ static int octeon_mgmt_open(struct net_device *netdev)
mix_ctl.s.nbtarb = 0; /* Arbitration mode */
/* MII CB-request FIFO programmable high watermark */
mix_ctl.s.mrq_hwm = 1;
- cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64);
+ cvmx_write_csr(p->mix + MIX_CTL, mix_ctl.u64);
if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)
|| OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) {
@@ -806,16 +845,16 @@ static int octeon_mgmt_open(struct net_device *netdev)
/* Clear statistics. */
/* Clear on read. */
- cvmx_write_csr(CVMX_AGL_GMX_RXX_STATS_CTL(port), 1);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_DRP(port), 0);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_BAD(port), 0);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_STATS_CTL, 1);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_STATS_PKTS_DRP, 0);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_STATS_PKTS_BAD, 0);
- cvmx_write_csr(CVMX_AGL_GMX_TXX_STATS_CTL(port), 1);
- cvmx_write_csr(CVMX_AGL_GMX_TXX_STAT0(port), 0);
- cvmx_write_csr(CVMX_AGL_GMX_TXX_STAT1(port), 0);
+ cvmx_write_csr(p->agl + AGL_GMX_TX_STATS_CTL, 1);
+ cvmx_write_csr(p->agl + AGL_GMX_TX_STAT0, 0);
+ cvmx_write_csr(p->agl + AGL_GMX_TX_STAT1, 0);
/* Clear any pending interrupts */
- cvmx_write_csr(CVMX_MIXX_ISR(port), cvmx_read_csr(CVMX_MIXX_ISR(port)));
+ cvmx_write_csr(p->mix + MIX_ISR, cvmx_read_csr(p->mix + MIX_ISR));
if (request_irq(p->irq, octeon_mgmt_interrupt, 0, netdev->name,
netdev)) {
@@ -826,18 +865,18 @@ static int octeon_mgmt_open(struct net_device *netdev)
/* Interrupt every single RX packet */
mix_irhwm.u64 = 0;
mix_irhwm.s.irhwm = 0;
- cvmx_write_csr(CVMX_MIXX_IRHWM(port), mix_irhwm.u64);
+ cvmx_write_csr(p->mix + MIX_IRHWM, mix_irhwm.u64);
/* Interrupt when we have 1 or more packets to clean. */
mix_orhwm.u64 = 0;
mix_orhwm.s.orhwm = 1;
- cvmx_write_csr(CVMX_MIXX_ORHWM(port), mix_orhwm.u64);
+ cvmx_write_csr(p->mix + MIX_ORHWM, mix_orhwm.u64);
/* Enable receive and transmit interrupts */
mix_intena.u64 = 0;
mix_intena.s.ithena = 1;
mix_intena.s.othena = 1;
- cvmx_write_csr(CVMX_MIXX_INTENA(port), mix_intena.u64);
+ cvmx_write_csr(p->mix + MIX_INTENA, mix_intena.u64);
/* Enable packet I/O. */
@@ -868,7 +907,7 @@ static int octeon_mgmt_open(struct net_device *netdev)
* frame. GMX checks that the PREAMBLE is sent correctly.
*/
rxx_frm_ctl.s.pre_chk = 1;
- cvmx_write_csr(CVMX_AGL_GMX_RXX_FRM_CTL(port), rxx_frm_ctl.u64);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_FRM_CTL, rxx_frm_ctl.u64);
/* Enable the AGL block */
agl_gmx_inf_mode.u64 = 0;
@@ -876,13 +915,13 @@ static int octeon_mgmt_open(struct net_device *netdev)
cvmx_write_csr(CVMX_AGL_GMX_INF_MODE, agl_gmx_inf_mode.u64);
/* Configure the port duplex and enables */
- prtx_cfg.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
+ prtx_cfg.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
prtx_cfg.s.tx_en = 1;
prtx_cfg.s.rx_en = 1;
prtx_cfg.s.en = 1;
p->last_duplex = 1;
prtx_cfg.s.duplex = p->last_duplex;
- cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), prtx_cfg.u64);
+ cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, prtx_cfg.u64);
p->last_link = 0;
netif_carrier_off(netdev);
@@ -946,7 +985,6 @@ static int octeon_mgmt_stop(struct net_device *netdev)
static int octeon_mgmt_xmit(struct sk_buff *skb, struct net_device *netdev)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
union mgmt_port_ring_entry re;
unsigned long flags;
int rv = NETDEV_TX_BUSY;
@@ -990,7 +1028,7 @@ static int octeon_mgmt_xmit(struct sk_buff *skb, struct net_device *netdev)
netdev->stats.tx_bytes += skb->len;
/* Ring the bell. */
- cvmx_write_csr(CVMX_MIXX_ORING2(port), 1);
+ cvmx_write_csr(p->mix + MIX_ORING2, 1);
rv = NETDEV_TX_OK;
out:
@@ -1069,10 +1107,14 @@ static const struct net_device_ops octeon_mgmt_ops = {
static int __devinit octeon_mgmt_probe(struct platform_device *pdev)
{
- struct resource *res_irq;
struct net_device *netdev;
struct octeon_mgmt *p;
- int i;
+ const __be32 *data;
+ const u8 *mac;
+ struct resource *res_mix;
+ struct resource *res_agl;
+ int len;
+ int result;
netdev = alloc_etherdev(sizeof(struct octeon_mgmt));
if (netdev == NULL)
@@ -1086,14 +1128,63 @@ static int __devinit octeon_mgmt_probe(struct platform_device *pdev)
p->netdev = netdev;
p->dev = &pdev->dev;
- p->port = pdev->id;
+ data = of_get_property(pdev->dev.of_node, "cell-index", &len);
+ if (data && len == sizeof(*data)) {
+ p->port = be32_to_cpup(data);
+ } else {
+ dev_err(&pdev->dev, "no 'cell-index' property\n");
+ result = -ENXIO;
+ goto err;
+ }
+
snprintf(netdev->name, IFNAMSIZ, "mgmt%d", p->port);
- res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res_irq)
+ result = platform_get_irq(pdev, 0);
+ if (result < 0)
+ goto err;
+
+ p->irq = result;
+
+ res_mix = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res_mix == NULL) {
+ dev_err(&pdev->dev, "no 'reg' resource\n");
+ result = -ENXIO;
+ goto err;
+ }
+
+ res_agl = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (res_agl == NULL) {
+ dev_err(&pdev->dev, "no 'reg' resource\n");
+ result = -ENXIO;
goto err;
+ }
+
+ p->mix_phys = res_mix->start;
+ p->mix_size = resource_size(res_mix);
+ p->agl_phys = res_agl->start;
+ p->agl_size = resource_size(res_agl);
+
+
+ if (!devm_request_mem_region(&pdev->dev, p->mix_phys, p->mix_size,
+ res_mix->name)) {
+ dev_err(&pdev->dev, "request_mem_region (%s) failed\n",
+ res_mix->name);
+ result = -ENXIO;
+ goto err;
+ }
+
+ if (!devm_request_mem_region(&pdev->dev, p->agl_phys, p->agl_size,
+ res_agl->name)) {
+ result = -ENXIO;
+ dev_err(&pdev->dev, "request_mem_region (%s) failed\n",
+ res_agl->name);
+ goto fail_region1;
+ }
+
+
+ p->mix = (u64)ioremap(p->mix_phys, p->mix_size);
+ p->agl = (u64)ioremap(p->agl_phys, p->agl_size);
- p->irq = res_irq->start;
spin_lock_init(&p->lock);
skb_queue_head_init(&p->tx_list);
@@ -1104,39 +1195,61 @@ static int __devinit octeon_mgmt_probe(struct platform_device *pdev)
netdev->netdev_ops = &octeon_mgmt_ops;
netdev->ethtool_ops = &octeon_mgmt_ethtool_ops;
- /* The mgmt ports get the first N MACs. */
- for (i = 0; i < 6; i++)
- netdev->dev_addr[i] = octeon_bootinfo->mac_addr_base[i];
- netdev->dev_addr[5] += p->port;
+ mac = of_get_mac_address(pdev->dev.of_node);
- if (p->port >= octeon_bootinfo->mac_addr_count)
- dev_err(&pdev->dev,
- "Error %s: Using MAC outside of the assigned range: %pM\n",
- netdev->name, netdev->dev_addr);
+ if (mac)
+ memcpy(netdev->dev_addr, mac, 6);
- if (register_netdev(netdev))
- goto err;
+ p->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
+
+ pdev->dev.coherent_dma_mask = DMA_BIT_MASK(64);
+ pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+
+ result = register_netdev(netdev);
+ if (result)
+ goto fail_region2;
dev_info(&pdev->dev, "Version " DRV_VERSION "\n");
return 0;
+
+fail_region2:
+ iounmap((void *)p->agl);
+ iounmap((void *)p->mix);
+ devm_release_mem_region(&pdev->dev, p->agl_phys, p->agl_size);
+fail_region1:
+ devm_release_mem_region(&pdev->dev, p->mix_phys, p->mix_size);
err:
free_netdev(netdev);
- return -ENOENT;
+ return result;
}
static int __devexit octeon_mgmt_remove(struct platform_device *pdev)
{
struct net_device *netdev = dev_get_drvdata(&pdev->dev);
+ struct octeon_mgmt *p = netdev_priv(netdev);
unregister_netdev(netdev);
+ iounmap((void *)p->agl);
+ iounmap((void *)p->mix);
+ devm_release_mem_region(&pdev->dev, p->agl_phys, p->agl_size);
+ devm_release_mem_region(&pdev->dev, p->mix_phys, p->mix_size);
free_netdev(netdev);
return 0;
}
+static struct of_device_id octeon_mgmt_match[] = {
+ {
+ .compatible = "cavium,octeon-5750-mix",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, octeon_mgmt_match);
+
static struct platform_driver octeon_mgmt_driver = {
.driver = {
.name = "octeon_mgmt",
.owner = THIS_MODULE,
+ .of_match_table = octeon_mgmt_match,
},
.probe = octeon_mgmt_probe,
.remove = __devexit_p(octeon_mgmt_remove),
--
1.7.2.3
^ permalink raw reply related [flat|nested] 40+ messages in thread* [RFC PATCH v2 11/12] netdev: octeon_mgmt: Convert to use device tree.
@ 2011-03-04 19:42 ` David Daney
0 siblings, 0 replies; 40+ messages in thread
From: David Daney @ 2011-03-04 19:42 UTC (permalink / raw)
To: linux-mips, ralf, devicetree-discuss, grant.likely, linux-kernel
Cc: David Daney, David S. Miller, netdev
The device tree will supply the register bank base addresses, make
register addressing relative to those. PHY connection is now
described by the device tree.
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: netdev@vger.kernel.org
---
arch/mips/cavium-octeon/octeon-platform.c | 62 ------
drivers/net/octeon/octeon_mgmt.c | 321 +++++++++++++++++++----------
2 files changed, 217 insertions(+), 166 deletions(-)
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
index ce471bd..104713c 100644
--- a/arch/mips/cavium-octeon/octeon-platform.c
+++ b/arch/mips/cavium-octeon/octeon-platform.c
@@ -168,68 +168,6 @@ out:
}
device_initcall(octeon_rng_device_init);
-/* Octeon mgmt port Ethernet interface. */
-static int __init octeon_mgmt_device_init(void)
-{
- struct platform_device *pd;
- int ret = 0;
- int port, num_ports;
-
- struct resource mgmt_port_resource = {
- .flags = IORESOURCE_IRQ,
- .start = -1,
- .end = -1
- };
-
- if (!OCTEON_IS_MODEL(OCTEON_CN56XX) && !OCTEON_IS_MODEL(OCTEON_CN52XX))
- return 0;
-
- if (OCTEON_IS_MODEL(OCTEON_CN56XX))
- num_ports = 1;
- else
- num_ports = 2;
-
- for (port = 0; port < num_ports; port++) {
- pd = platform_device_alloc("octeon_mgmt", port);
- if (!pd) {
- ret = -ENOMEM;
- goto out;
- }
- /* No DMA restrictions */
- pd->dev.coherent_dma_mask = DMA_BIT_MASK(64);
- pd->dev.dma_mask = &pd->dev.coherent_dma_mask;
-
- switch (port) {
- case 0:
- mgmt_port_resource.start = OCTEON_IRQ_MII0;
- break;
- case 1:
- mgmt_port_resource.start = OCTEON_IRQ_MII1;
- break;
- default:
- BUG();
- }
- mgmt_port_resource.end = mgmt_port_resource.start;
-
- ret = platform_device_add_resources(pd, &mgmt_port_resource, 1);
-
- if (ret)
- goto fail;
-
- ret = platform_device_add(pd);
- if (ret)
- goto fail;
- }
- return ret;
-fail:
- platform_device_put(pd);
-
-out:
- return ret;
-
-}
-device_initcall(octeon_mgmt_device_init);
-
#ifdef CONFIG_USB
static int __init octeon_ehci_device_init(void)
diff --git a/drivers/net/octeon/octeon_mgmt.c b/drivers/net/octeon/octeon_mgmt.c
index b264f0f..17be326 100644
--- a/drivers/net/octeon/octeon_mgmt.c
+++ b/drivers/net/octeon/octeon_mgmt.c
@@ -6,16 +6,18 @@
* Copyright (C) 2009 Cavium Networks
*/
-#include <linux/capability.h>
-#include <linux/dma-mapping.h>
-#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/netdevice.h>
+#include <linux/dma-mapping.h>
#include <linux/etherdevice.h>
+#include <linux/capability.h>
+#include <linux/netdevice.h>
+#include <linux/spinlock.h>
#include <linux/if_vlan.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
+#include <linux/init.h>
#include <linux/slab.h>
#include <linux/phy.h>
-#include <linux/spinlock.h>
#include <asm/octeon/octeon.h>
#include <asm/octeon/cvmx-mixx-defs.h>
@@ -55,8 +57,56 @@ union mgmt_port_ring_entry {
} s;
};
+#define MIX_ORING1 0x0
+#define MIX_ORING2 0x8
+#define MIX_IRING1 0x10
+#define MIX_IRING2 0x18
+#define MIX_CTL 0x20
+#define MIX_IRHWM 0x28
+#define MIX_IRCNT 0x30
+#define MIX_ORHWM 0x38
+#define MIX_ORCNT 0x40
+#define MIX_ISR 0x48
+#define MIX_INTENA 0x50
+#define MIX_REMCNT 0x58
+#define MIX_BIST 0x78
+
+#define AGL_GMX_PRT_CFG 0x10
+#define AGL_GMX_RX_FRM_CTL 0x18
+#define AGL_GMX_RX_FRM_MAX 0x30
+#define AGL_GMX_RX_JABBER 0x38
+#define AGL_GMX_RX_STATS_CTL 0x50
+
+#define AGL_GMX_RX_STATS_PKTS_DRP 0xb0
+#define AGL_GMX_RX_STATS_OCTS_DRP 0xb8
+#define AGL_GMX_RX_STATS_PKTS_BAD 0xc0
+
+#define AGL_GMX_RX_ADR_CTL 0x100
+#define AGL_GMX_RX_ADR_CAM_EN 0x108
+#define AGL_GMX_RX_ADR_CAM0 0x180
+#define AGL_GMX_RX_ADR_CAM1 0x188
+#define AGL_GMX_RX_ADR_CAM2 0x190
+#define AGL_GMX_RX_ADR_CAM3 0x198
+#define AGL_GMX_RX_ADR_CAM4 0x1a0
+#define AGL_GMX_RX_ADR_CAM5 0x1a8
+
+#define AGL_GMX_TX_STATS_CTL 0x268
+#define AGL_GMX_TX_CTL 0x270
+#define AGL_GMX_TX_STAT0 0x280
+#define AGL_GMX_TX_STAT1 0x288
+#define AGL_GMX_TX_STAT2 0x290
+#define AGL_GMX_TX_STAT3 0x298
+#define AGL_GMX_TX_STAT4 0x2a0
+#define AGL_GMX_TX_STAT5 0x2a8
+#define AGL_GMX_TX_STAT6 0x2b0
+#define AGL_GMX_TX_STAT7 0x2b8
+#define AGL_GMX_TX_STAT8 0x2c0
+#define AGL_GMX_TX_STAT9 0x2c8
+
struct octeon_mgmt {
struct net_device *netdev;
+ u64 mix;
+ u64 agl;
int port;
int irq;
u64 *tx_ring;
@@ -82,31 +132,34 @@ struct octeon_mgmt {
struct napi_struct napi;
struct tasklet_struct tx_clean_tasklet;
struct phy_device *phydev;
+ struct device_node *phy_np;
+ resource_size_t mix_phys;
+ resource_size_t mix_size;
+ resource_size_t agl_phys;
+ resource_size_t agl_size;
};
static void octeon_mgmt_set_rx_irq(struct octeon_mgmt *p, int enable)
{
- int port = p->port;
union cvmx_mixx_intena mix_intena;
unsigned long flags;
spin_lock_irqsave(&p->lock, flags);
- mix_intena.u64 = cvmx_read_csr(CVMX_MIXX_INTENA(port));
+ mix_intena.u64 = cvmx_read_csr(p->mix + MIX_INTENA);
mix_intena.s.ithena = enable ? 1 : 0;
- cvmx_write_csr(CVMX_MIXX_INTENA(port), mix_intena.u64);
+ cvmx_write_csr(p->mix + MIX_INTENA, mix_intena.u64);
spin_unlock_irqrestore(&p->lock, flags);
}
static void octeon_mgmt_set_tx_irq(struct octeon_mgmt *p, int enable)
{
- int port = p->port;
union cvmx_mixx_intena mix_intena;
unsigned long flags;
spin_lock_irqsave(&p->lock, flags);
- mix_intena.u64 = cvmx_read_csr(CVMX_MIXX_INTENA(port));
+ mix_intena.u64 = cvmx_read_csr(p->mix + MIX_INTENA);
mix_intena.s.othena = enable ? 1 : 0;
- cvmx_write_csr(CVMX_MIXX_INTENA(port), mix_intena.u64);
+ cvmx_write_csr(p->mix + MIX_INTENA, mix_intena.u64);
spin_unlock_irqrestore(&p->lock, flags);
}
@@ -143,7 +196,6 @@ static unsigned int ring_size_to_bytes(unsigned int ring_size)
static void octeon_mgmt_rx_fill_ring(struct net_device *netdev)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
while (p->rx_current_fill < ring_max_fill(OCTEON_MGMT_RX_RING_SIZE)) {
unsigned int size;
@@ -174,24 +226,23 @@ static void octeon_mgmt_rx_fill_ring(struct net_device *netdev)
(p->rx_next_fill + 1) % OCTEON_MGMT_RX_RING_SIZE;
p->rx_current_fill++;
/* Ring the bell. */
- cvmx_write_csr(CVMX_MIXX_IRING2(port), 1);
+ cvmx_write_csr(p->mix + MIX_IRING2, 1);
}
}
static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p)
{
- int port = p->port;
union cvmx_mixx_orcnt mix_orcnt;
union mgmt_port_ring_entry re;
struct sk_buff *skb;
int cleaned = 0;
unsigned long flags;
- mix_orcnt.u64 = cvmx_read_csr(CVMX_MIXX_ORCNT(port));
+ mix_orcnt.u64 = cvmx_read_csr(p->mix + MIX_ORCNT);
while (mix_orcnt.s.orcnt) {
spin_lock_irqsave(&p->tx_list.lock, flags);
- mix_orcnt.u64 = cvmx_read_csr(CVMX_MIXX_ORCNT(port));
+ mix_orcnt.u64 = cvmx_read_csr(p->mix + MIX_ORCNT);
if (mix_orcnt.s.orcnt == 0) {
spin_unlock_irqrestore(&p->tx_list.lock, flags);
@@ -211,7 +262,7 @@ static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p)
mix_orcnt.s.orcnt = 1;
/* Acknowledge to hardware that we have the buffer. */
- cvmx_write_csr(CVMX_MIXX_ORCNT(port), mix_orcnt.u64);
+ cvmx_write_csr(p->mix + MIX_ORCNT, mix_orcnt.u64);
p->tx_current_fill--;
spin_unlock_irqrestore(&p->tx_list.lock, flags);
@@ -221,7 +272,7 @@ static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p)
dev_kfree_skb_any(skb);
cleaned++;
- mix_orcnt.u64 = cvmx_read_csr(CVMX_MIXX_ORCNT(port));
+ mix_orcnt.u64 = cvmx_read_csr(p->mix + MIX_ORCNT);
}
if (cleaned && netif_queue_stopped(p->netdev))
@@ -238,13 +289,12 @@ static void octeon_mgmt_clean_tx_tasklet(unsigned long arg)
static void octeon_mgmt_update_rx_stats(struct net_device *netdev)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
unsigned long flags;
u64 drop, bad;
/* These reads also clear the count registers. */
- drop = cvmx_read_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_DRP(port));
- bad = cvmx_read_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_BAD(port));
+ drop = cvmx_read_csr(p->agl + AGL_GMX_RX_STATS_PKTS_DRP);
+ bad = cvmx_read_csr(p->agl + AGL_GMX_RX_STATS_PKTS_BAD);
if (drop || bad) {
/* Do an atomic update. */
@@ -258,15 +308,14 @@ static void octeon_mgmt_update_rx_stats(struct net_device *netdev)
static void octeon_mgmt_update_tx_stats(struct net_device *netdev)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
unsigned long flags;
union cvmx_agl_gmx_txx_stat0 s0;
union cvmx_agl_gmx_txx_stat1 s1;
/* These reads also clear the count registers. */
- s0.u64 = cvmx_read_csr(CVMX_AGL_GMX_TXX_STAT0(port));
- s1.u64 = cvmx_read_csr(CVMX_AGL_GMX_TXX_STAT1(port));
+ s0.u64 = cvmx_read_csr(p->agl + AGL_GMX_TX_STAT0);
+ s1.u64 = cvmx_read_csr(p->agl + AGL_GMX_TX_STAT1);
if (s0.s.xsdef || s0.s.xscol || s1.s.scol || s1.s.mcol) {
/* Do an atomic update. */
@@ -305,7 +354,6 @@ static u64 octeon_mgmt_dequeue_rx_buffer(struct octeon_mgmt *p,
static int octeon_mgmt_receive_one(struct octeon_mgmt *p)
{
- int port = p->port;
struct net_device *netdev = p->netdev;
union cvmx_mixx_ircnt mix_ircnt;
union mgmt_port_ring_entry re;
@@ -378,18 +426,17 @@ done:
/* Tell the hardware we processed a packet. */
mix_ircnt.u64 = 0;
mix_ircnt.s.ircnt = 1;
- cvmx_write_csr(CVMX_MIXX_IRCNT(port), mix_ircnt.u64);
+ cvmx_write_csr(p->mix + MIX_IRCNT, mix_ircnt.u64);
return rc;
}
static int octeon_mgmt_receive_packets(struct octeon_mgmt *p, int budget)
{
- int port = p->port;
unsigned int work_done = 0;
union cvmx_mixx_ircnt mix_ircnt;
int rc;
- mix_ircnt.u64 = cvmx_read_csr(CVMX_MIXX_IRCNT(port));
+ mix_ircnt.u64 = cvmx_read_csr(p->mix + MIX_IRCNT);
while (work_done < budget && mix_ircnt.s.ircnt) {
rc = octeon_mgmt_receive_one(p);
@@ -397,7 +444,7 @@ static int octeon_mgmt_receive_packets(struct octeon_mgmt *p, int budget)
work_done++;
/* Check for more packets. */
- mix_ircnt.u64 = cvmx_read_csr(CVMX_MIXX_IRCNT(port));
+ mix_ircnt.u64 = cvmx_read_csr(p->mix + MIX_IRCNT);
}
octeon_mgmt_rx_fill_ring(p->netdev);
@@ -431,16 +478,16 @@ static void octeon_mgmt_reset_hw(struct octeon_mgmt *p)
union cvmx_agl_gmx_bist agl_gmx_bist;
mix_ctl.u64 = 0;
- cvmx_write_csr(CVMX_MIXX_CTL(p->port), mix_ctl.u64);
+ cvmx_write_csr(p->mix + MIX_CTL, mix_ctl.u64);
do {
- mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(p->port));
+ mix_ctl.u64 = cvmx_read_csr(p->mix + MIX_CTL);
} while (mix_ctl.s.busy);
mix_ctl.s.reset = 1;
- cvmx_write_csr(CVMX_MIXX_CTL(p->port), mix_ctl.u64);
- cvmx_read_csr(CVMX_MIXX_CTL(p->port));
+ cvmx_write_csr(p->mix + MIX_CTL, mix_ctl.u64);
+ cvmx_read_csr(p->mix + MIX_CTL);
cvmx_wait(64);
- mix_bist.u64 = cvmx_read_csr(CVMX_MIXX_BIST(p->port));
+ mix_bist.u64 = cvmx_read_csr(p->mix + MIX_BIST);
if (mix_bist.u64)
dev_warn(p->dev, "MIX failed BIST (0x%016llx)\n",
(unsigned long long)mix_bist.u64);
@@ -471,7 +518,6 @@ static void octeon_mgmt_cam_state_add(struct octeon_mgmt_cam_state *cs,
static void octeon_mgmt_set_rx_filtering(struct net_device *netdev)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
union cvmx_agl_gmx_rxx_adr_ctl adr_ctl;
union cvmx_agl_gmx_prtx_cfg agl_gmx_prtx;
unsigned long flags;
@@ -517,29 +563,29 @@ static void octeon_mgmt_set_rx_filtering(struct net_device *netdev)
spin_lock_irqsave(&p->lock, flags);
/* Disable packet I/O. */
- agl_gmx_prtx.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
+ agl_gmx_prtx.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
prev_packet_enable = agl_gmx_prtx.s.en;
agl_gmx_prtx.s.en = 0;
- cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_prtx.u64);
+ cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, agl_gmx_prtx.u64);
adr_ctl.u64 = 0;
adr_ctl.s.cam_mode = cam_mode;
adr_ctl.s.mcst = multicast_mode;
adr_ctl.s.bcst = 1; /* Allow broadcast */
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CTL(port), adr_ctl.u64);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CTL, adr_ctl.u64);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM0(port), cam_state.cam[0]);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM1(port), cam_state.cam[1]);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM2(port), cam_state.cam[2]);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM3(port), cam_state.cam[3]);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM4(port), cam_state.cam[4]);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM5(port), cam_state.cam[5]);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM_EN(port), cam_state.cam_mask);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM0, cam_state.cam[0]);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM1, cam_state.cam[1]);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM2, cam_state.cam[2]);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM3, cam_state.cam[3]);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM4, cam_state.cam[4]);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM5, cam_state.cam[5]);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM_EN, cam_state.cam_mask);
/* Restore packet I/O. */
agl_gmx_prtx.s.en = prev_packet_enable;
- cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_prtx.u64);
+ cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, agl_gmx_prtx.u64);
spin_unlock_irqrestore(&p->lock, flags);
}
@@ -561,7 +607,6 @@ static int octeon_mgmt_set_mac_address(struct net_device *netdev, void *addr)
static int octeon_mgmt_change_mtu(struct net_device *netdev, int new_mtu)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
int size_without_fcs = new_mtu + OCTEON_MGMT_RX_HEADROOM;
/*
@@ -577,8 +622,8 @@ static int octeon_mgmt_change_mtu(struct net_device *netdev, int new_mtu)
netdev->mtu = new_mtu;
- cvmx_write_csr(CVMX_AGL_GMX_RXX_FRM_MAX(port), size_without_fcs);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_JABBER(port),
+ cvmx_write_csr(p->agl + AGL_GMX_RX_FRM_MAX, size_without_fcs);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_JABBER,
(size_without_fcs + 7) & 0xfff8);
return 0;
@@ -588,14 +633,13 @@ static irqreturn_t octeon_mgmt_interrupt(int cpl, void *dev_id)
{
struct net_device *netdev = dev_id;
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
union cvmx_mixx_isr mixx_isr;
- mixx_isr.u64 = cvmx_read_csr(CVMX_MIXX_ISR(port));
+ mixx_isr.u64 = cvmx_read_csr(p->mix + MIX_ISR);
/* Clear any pending interrupts */
- cvmx_write_csr(CVMX_MIXX_ISR(port), mixx_isr.u64);
- cvmx_read_csr(CVMX_MIXX_ISR(port));
+ cvmx_write_csr(p->mix + MIX_ISR, mixx_isr.u64);
+ cvmx_read_csr(p->mix + MIX_ISR);
if (mixx_isr.s.irthresh) {
octeon_mgmt_disable_rx_irq(p);
@@ -626,7 +670,6 @@ static int octeon_mgmt_ioctl(struct net_device *netdev,
static void octeon_mgmt_adjust_link(struct net_device *netdev)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
union cvmx_agl_gmx_prtx_cfg prtx_cfg;
unsigned long flags;
int link_changed = 0;
@@ -637,11 +680,9 @@ static void octeon_mgmt_adjust_link(struct net_device *netdev)
link_changed = 1;
if (p->last_duplex != p->phydev->duplex) {
p->last_duplex = p->phydev->duplex;
- prtx_cfg.u64 =
- cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
+ prtx_cfg.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
prtx_cfg.s.duplex = p->phydev->duplex;
- cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port),
- prtx_cfg.u64);
+ cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, prtx_cfg.u64);
}
} else {
if (p->last_link)
@@ -667,18 +708,16 @@ static void octeon_mgmt_adjust_link(struct net_device *netdev)
static int octeon_mgmt_init_phy(struct net_device *netdev)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- char phy_id[20];
- if (octeon_is_simulation()) {
+ if (octeon_is_simulation() || p->phy_np == NULL) {
/* No PHYs in the simulator. */
netif_carrier_on(netdev);
return 0;
}
- snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "0", p->port);
-
- p->phydev = phy_connect(netdev, phy_id, octeon_mgmt_adjust_link, 0,
- PHY_INTERFACE_MODE_MII);
+ p->phydev = of_phy_connect(netdev, p->phy_np,
+ octeon_mgmt_adjust_link, 0,
+ PHY_INTERFACE_MODE_MII);
if (IS_ERR(p->phydev)) {
p->phydev = NULL;
@@ -734,14 +773,14 @@ static int octeon_mgmt_open(struct net_device *netdev)
octeon_mgmt_reset_hw(p);
- mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(port));
+ mix_ctl.u64 = cvmx_read_csr(p->mix + MIX_CTL);
/* Bring it out of reset if needed. */
if (mix_ctl.s.reset) {
mix_ctl.s.reset = 0;
- cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64);
+ cvmx_write_csr(p->mix + MIX_CTL, mix_ctl.u64);
do {
- mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(port));
+ mix_ctl.u64 = cvmx_read_csr(p->mix + MIX_CTL);
} while (mix_ctl.s.reset);
}
@@ -752,17 +791,17 @@ static int octeon_mgmt_open(struct net_device *netdev)
oring1.u64 = 0;
oring1.s.obase = p->tx_ring_handle >> 3;
oring1.s.osize = OCTEON_MGMT_TX_RING_SIZE;
- cvmx_write_csr(CVMX_MIXX_ORING1(port), oring1.u64);
+ cvmx_write_csr(p->mix + MIX_ORING1, oring1.u64);
iring1.u64 = 0;
iring1.s.ibase = p->rx_ring_handle >> 3;
iring1.s.isize = OCTEON_MGMT_RX_RING_SIZE;
- cvmx_write_csr(CVMX_MIXX_IRING1(port), iring1.u64);
+ cvmx_write_csr(p->mix + MIX_IRING1, iring1.u64);
/* Disable packet I/O. */
- prtx_cfg.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
+ prtx_cfg.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
prtx_cfg.s.en = 0;
- cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), prtx_cfg.u64);
+ cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, prtx_cfg.u64);
memcpy(sa.sa_data, netdev->dev_addr, ETH_ALEN);
octeon_mgmt_set_mac_address(netdev, &sa);
@@ -779,7 +818,7 @@ static int octeon_mgmt_open(struct net_device *netdev)
mix_ctl.s.nbtarb = 0; /* Arbitration mode */
/* MII CB-request FIFO programmable high watermark */
mix_ctl.s.mrq_hwm = 1;
- cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64);
+ cvmx_write_csr(p->mix + MIX_CTL, mix_ctl.u64);
if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)
|| OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) {
@@ -806,16 +845,16 @@ static int octeon_mgmt_open(struct net_device *netdev)
/* Clear statistics. */
/* Clear on read. */
- cvmx_write_csr(CVMX_AGL_GMX_RXX_STATS_CTL(port), 1);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_DRP(port), 0);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_BAD(port), 0);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_STATS_CTL, 1);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_STATS_PKTS_DRP, 0);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_STATS_PKTS_BAD, 0);
- cvmx_write_csr(CVMX_AGL_GMX_TXX_STATS_CTL(port), 1);
- cvmx_write_csr(CVMX_AGL_GMX_TXX_STAT0(port), 0);
- cvmx_write_csr(CVMX_AGL_GMX_TXX_STAT1(port), 0);
+ cvmx_write_csr(p->agl + AGL_GMX_TX_STATS_CTL, 1);
+ cvmx_write_csr(p->agl + AGL_GMX_TX_STAT0, 0);
+ cvmx_write_csr(p->agl + AGL_GMX_TX_STAT1, 0);
/* Clear any pending interrupts */
- cvmx_write_csr(CVMX_MIXX_ISR(port), cvmx_read_csr(CVMX_MIXX_ISR(port)));
+ cvmx_write_csr(p->mix + MIX_ISR, cvmx_read_csr(p->mix + MIX_ISR));
if (request_irq(p->irq, octeon_mgmt_interrupt, 0, netdev->name,
netdev)) {
@@ -826,18 +865,18 @@ static int octeon_mgmt_open(struct net_device *netdev)
/* Interrupt every single RX packet */
mix_irhwm.u64 = 0;
mix_irhwm.s.irhwm = 0;
- cvmx_write_csr(CVMX_MIXX_IRHWM(port), mix_irhwm.u64);
+ cvmx_write_csr(p->mix + MIX_IRHWM, mix_irhwm.u64);
/* Interrupt when we have 1 or more packets to clean. */
mix_orhwm.u64 = 0;
mix_orhwm.s.orhwm = 1;
- cvmx_write_csr(CVMX_MIXX_ORHWM(port), mix_orhwm.u64);
+ cvmx_write_csr(p->mix + MIX_ORHWM, mix_orhwm.u64);
/* Enable receive and transmit interrupts */
mix_intena.u64 = 0;
mix_intena.s.ithena = 1;
mix_intena.s.othena = 1;
- cvmx_write_csr(CVMX_MIXX_INTENA(port), mix_intena.u64);
+ cvmx_write_csr(p->mix + MIX_INTENA, mix_intena.u64);
/* Enable packet I/O. */
@@ -868,7 +907,7 @@ static int octeon_mgmt_open(struct net_device *netdev)
* frame. GMX checks that the PREAMBLE is sent correctly.
*/
rxx_frm_ctl.s.pre_chk = 1;
- cvmx_write_csr(CVMX_AGL_GMX_RXX_FRM_CTL(port), rxx_frm_ctl.u64);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_FRM_CTL, rxx_frm_ctl.u64);
/* Enable the AGL block */
agl_gmx_inf_mode.u64 = 0;
@@ -876,13 +915,13 @@ static int octeon_mgmt_open(struct net_device *netdev)
cvmx_write_csr(CVMX_AGL_GMX_INF_MODE, agl_gmx_inf_mode.u64);
/* Configure the port duplex and enables */
- prtx_cfg.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
+ prtx_cfg.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
prtx_cfg.s.tx_en = 1;
prtx_cfg.s.rx_en = 1;
prtx_cfg.s.en = 1;
p->last_duplex = 1;
prtx_cfg.s.duplex = p->last_duplex;
- cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), prtx_cfg.u64);
+ cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, prtx_cfg.u64);
p->last_link = 0;
netif_carrier_off(netdev);
@@ -946,7 +985,6 @@ static int octeon_mgmt_stop(struct net_device *netdev)
static int octeon_mgmt_xmit(struct sk_buff *skb, struct net_device *netdev)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
union mgmt_port_ring_entry re;
unsigned long flags;
int rv = NETDEV_TX_BUSY;
@@ -990,7 +1028,7 @@ static int octeon_mgmt_xmit(struct sk_buff *skb, struct net_device *netdev)
netdev->stats.tx_bytes += skb->len;
/* Ring the bell. */
- cvmx_write_csr(CVMX_MIXX_ORING2(port), 1);
+ cvmx_write_csr(p->mix + MIX_ORING2, 1);
rv = NETDEV_TX_OK;
out:
@@ -1069,10 +1107,14 @@ static const struct net_device_ops octeon_mgmt_ops = {
static int __devinit octeon_mgmt_probe(struct platform_device *pdev)
{
- struct resource *res_irq;
struct net_device *netdev;
struct octeon_mgmt *p;
- int i;
+ const __be32 *data;
+ const u8 *mac;
+ struct resource *res_mix;
+ struct resource *res_agl;
+ int len;
+ int result;
netdev = alloc_etherdev(sizeof(struct octeon_mgmt));
if (netdev == NULL)
@@ -1086,14 +1128,63 @@ static int __devinit octeon_mgmt_probe(struct platform_device *pdev)
p->netdev = netdev;
p->dev = &pdev->dev;
- p->port = pdev->id;
+ data = of_get_property(pdev->dev.of_node, "cell-index", &len);
+ if (data && len == sizeof(*data)) {
+ p->port = be32_to_cpup(data);
+ } else {
+ dev_err(&pdev->dev, "no 'cell-index' property\n");
+ result = -ENXIO;
+ goto err;
+ }
+
snprintf(netdev->name, IFNAMSIZ, "mgmt%d", p->port);
- res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res_irq)
+ result = platform_get_irq(pdev, 0);
+ if (result < 0)
+ goto err;
+
+ p->irq = result;
+
+ res_mix = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res_mix == NULL) {
+ dev_err(&pdev->dev, "no 'reg' resource\n");
+ result = -ENXIO;
+ goto err;
+ }
+
+ res_agl = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (res_agl == NULL) {
+ dev_err(&pdev->dev, "no 'reg' resource\n");
+ result = -ENXIO;
goto err;
+ }
+
+ p->mix_phys = res_mix->start;
+ p->mix_size = resource_size(res_mix);
+ p->agl_phys = res_agl->start;
+ p->agl_size = resource_size(res_agl);
+
+
+ if (!devm_request_mem_region(&pdev->dev, p->mix_phys, p->mix_size,
+ res_mix->name)) {
+ dev_err(&pdev->dev, "request_mem_region (%s) failed\n",
+ res_mix->name);
+ result = -ENXIO;
+ goto err;
+ }
+
+ if (!devm_request_mem_region(&pdev->dev, p->agl_phys, p->agl_size,
+ res_agl->name)) {
+ result = -ENXIO;
+ dev_err(&pdev->dev, "request_mem_region (%s) failed\n",
+ res_agl->name);
+ goto fail_region1;
+ }
+
+
+ p->mix = (u64)ioremap(p->mix_phys, p->mix_size);
+ p->agl = (u64)ioremap(p->agl_phys, p->agl_size);
- p->irq = res_irq->start;
spin_lock_init(&p->lock);
skb_queue_head_init(&p->tx_list);
@@ -1104,39 +1195,61 @@ static int __devinit octeon_mgmt_probe(struct platform_device *pdev)
netdev->netdev_ops = &octeon_mgmt_ops;
netdev->ethtool_ops = &octeon_mgmt_ethtool_ops;
- /* The mgmt ports get the first N MACs. */
- for (i = 0; i < 6; i++)
- netdev->dev_addr[i] = octeon_bootinfo->mac_addr_base[i];
- netdev->dev_addr[5] += p->port;
+ mac = of_get_mac_address(pdev->dev.of_node);
- if (p->port >= octeon_bootinfo->mac_addr_count)
- dev_err(&pdev->dev,
- "Error %s: Using MAC outside of the assigned range: %pM\n",
- netdev->name, netdev->dev_addr);
+ if (mac)
+ memcpy(netdev->dev_addr, mac, 6);
- if (register_netdev(netdev))
- goto err;
+ p->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
+
+ pdev->dev.coherent_dma_mask = DMA_BIT_MASK(64);
+ pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+
+ result = register_netdev(netdev);
+ if (result)
+ goto fail_region2;
dev_info(&pdev->dev, "Version " DRV_VERSION "\n");
return 0;
+
+fail_region2:
+ iounmap((void *)p->agl);
+ iounmap((void *)p->mix);
+ devm_release_mem_region(&pdev->dev, p->agl_phys, p->agl_size);
+fail_region1:
+ devm_release_mem_region(&pdev->dev, p->mix_phys, p->mix_size);
err:
free_netdev(netdev);
- return -ENOENT;
+ return result;
}
static int __devexit octeon_mgmt_remove(struct platform_device *pdev)
{
struct net_device *netdev = dev_get_drvdata(&pdev->dev);
+ struct octeon_mgmt *p = netdev_priv(netdev);
unregister_netdev(netdev);
+ iounmap((void *)p->agl);
+ iounmap((void *)p->mix);
+ devm_release_mem_region(&pdev->dev, p->agl_phys, p->agl_size);
+ devm_release_mem_region(&pdev->dev, p->mix_phys, p->mix_size);
free_netdev(netdev);
return 0;
}
+static struct of_device_id octeon_mgmt_match[] = {
+ {
+ .compatible = "cavium,octeon-5750-mix",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, octeon_mgmt_match);
+
static struct platform_driver octeon_mgmt_driver = {
.driver = {
.name = "octeon_mgmt",
.owner = THIS_MODULE,
+ .of_match_table = octeon_mgmt_match,
},
.probe = octeon_mgmt_probe,
.remove = __devexit_p(octeon_mgmt_remove),
--
1.7.2.3
^ permalink raw reply related [flat|nested] 40+ messages in thread* Re: [RFC PATCH v2 11/12] netdev: octeon_mgmt: Convert to use device tree.
2011-03-04 19:42 ` David Daney
(?)
@ 2011-03-04 21:10 ` David Miller
-1 siblings, 0 replies; 40+ messages in thread
From: David Miller @ 2011-03-04 21:10 UTC (permalink / raw)
To: ddaney
Cc: linux-mips, ralf, devicetree-discuss, grant.likely, linux-kernel,
netdev
From: David Daney <ddaney@caviumnetworks.com>
Date: Fri, 4 Mar 2011 11:42:23 -0800
> The device tree will supply the register bank base addresses, make
> register addressing relative to those. PHY connection is now
> described by the device tree.
>
> Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Acked-by: David S. Miller <davem@davemloft.net>
^ permalink raw reply [flat|nested] 40+ messages in thread
* [RFC PATCH v2 12/12] staging: octeon_ethernet: Convert to use device tree.
2011-03-04 19:42 ` David Daney
@ 2011-03-04 19:42 ` David Daney
-1 siblings, 0 replies; 40+ messages in thread
From: David Daney @ 2011-03-04 19:42 UTC (permalink / raw)
To: linux-mips-6z/3iImG2C8G8FEW9MqTrA, ralf-6z/3iImG2C8G8FEW9MqTrA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
grant.likely-s3s/WqlpOiPyB63q8FvJNQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: netdev-u79uwXL29TY76Z2rM5mHXA, David Daney, David S. Miller
Get MAC address and PHY connection from the device tree.
Signed-off-by: David Daney <ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8@public.gmane.org>
Cc: "David S. Miller" <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
Cc: netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
---
drivers/staging/octeon/ethernet-mdio.c | 27 +++++----
drivers/staging/octeon/ethernet.c | 88 +++++++++++++++++-------------
drivers/staging/octeon/octeon-ethernet.h | 3 +
3 files changed, 69 insertions(+), 49 deletions(-)
diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c
index 0e5dab7..38a0153 100644
--- a/drivers/staging/octeon/ethernet-mdio.c
+++ b/drivers/staging/octeon/ethernet-mdio.c
@@ -27,6 +27,7 @@
#include <linux/kernel.h>
#include <linux/ethtool.h>
#include <linux/phy.h>
+#include <linux/of_mdio.h>
#include <net/dst.h>
@@ -162,22 +163,24 @@ static void cvm_oct_adjust_link(struct net_device *dev)
int cvm_oct_phy_setup_device(struct net_device *dev)
{
struct octeon_ethernet *priv = netdev_priv(dev);
+ struct device_node *phy_node;
- int phy_addr = cvmx_helper_board_get_mii_address(priv->port);
- if (phy_addr != -1) {
- char phy_id[20];
+ if (!priv->of_node)
+ return 0;
- snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "0", phy_addr);
+ phy_node = of_parse_phandle(priv->of_node, "phy-handle", 0);
+ if (!phy_node)
+ return 0;
- priv->phydev = phy_connect(dev, phy_id, cvm_oct_adjust_link, 0,
- PHY_INTERFACE_MODE_GMII);
+ priv->phydev = of_phy_connect(dev, phy_node, cvm_oct_adjust_link, 0,
+ PHY_INTERFACE_MODE_GMII);
- if (IS_ERR(priv->phydev)) {
- priv->phydev = NULL;
- return -1;
- }
- priv->last_link = 0;
- phy_start_aneg(priv->phydev);
+ if (IS_ERR(priv->phydev)) {
+ priv->phydev = NULL;
+ return -1;
}
+ priv->last_link = 0;
+ phy_start_aneg(priv->phydev);
+
return 0;
}
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index 042adf7..16c93e4 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -31,6 +31,7 @@
#include <linux/etherdevice.h>
#include <linux/phy.h>
#include <linux/slab.h>
+#include <linux/of_net.h>
#include <net/dst.h>
@@ -112,15 +113,6 @@ int rx_napi_weight = 32;
module_param(rx_napi_weight, int, 0444);
MODULE_PARM_DESC(rx_napi_weight, "The NAPI WEIGHT parameter.");
-/*
- * The offset from mac_addr_base that should be used for the next port
- * that is configured. By convention, if any mgmt ports exist on the
- * chip, they get the first mac addresses, The ports controlled by
- * this driver are numbered sequencially following any mgmt addresses
- * that may exist.
- */
-static unsigned int cvm_oct_mac_addr_offset;
-
/**
* cvm_oct_poll_queue - Workqueue for polling operations.
*/
@@ -447,26 +439,13 @@ static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr)
int cvm_oct_common_init(struct net_device *dev)
{
struct octeon_ethernet *priv = netdev_priv(dev);
- struct sockaddr sa;
- u64 mac = ((u64)(octeon_bootinfo->mac_addr_base[0] & 0xff) << 40) |
- ((u64)(octeon_bootinfo->mac_addr_base[1] & 0xff) << 32) |
- ((u64)(octeon_bootinfo->mac_addr_base[2] & 0xff) << 24) |
- ((u64)(octeon_bootinfo->mac_addr_base[3] & 0xff) << 16) |
- ((u64)(octeon_bootinfo->mac_addr_base[4] & 0xff) << 8) |
- (u64)(octeon_bootinfo->mac_addr_base[5] & 0xff);
-
- mac += cvm_oct_mac_addr_offset;
- sa.sa_data[0] = (mac >> 40) & 0xff;
- sa.sa_data[1] = (mac >> 32) & 0xff;
- sa.sa_data[2] = (mac >> 24) & 0xff;
- sa.sa_data[3] = (mac >> 16) & 0xff;
- sa.sa_data[4] = (mac >> 8) & 0xff;
- sa.sa_data[5] = mac & 0xff;
-
- if (cvm_oct_mac_addr_offset >= octeon_bootinfo->mac_addr_count)
- printk(KERN_DEBUG "%s: Using MAC outside of the assigned range:"
- " %pM\n", dev->name, sa.sa_data);
- cvm_oct_mac_addr_offset++;
+ struct sockaddr sa = {0};
+
+ if (priv->of_node) {
+ const u8 *mac = of_get_mac_address(priv->of_node);
+ if (mac)
+ memcpy(sa.sa_data, mac, 6);
+ }
/*
* Force the interface to use the POW send if always_use_pow
@@ -594,22 +573,55 @@ static const struct net_device_ops cvm_oct_pow_netdev_ops = {
extern void octeon_mdiobus_force_mod_depencency(void);
+static struct device_node * __init cvm_oct_of_get_child(const struct device_node *parent,
+ int reg_val)
+{
+ struct device_node *node = NULL;
+ int size;
+ const __be32 *addr;
+
+ for (;;) {
+ node = of_get_next_child(parent, node);
+ if (!node)
+ break;
+ addr = of_get_property(node, "reg", &size);
+ if (addr && (be32_to_cpu(*addr) == reg_val))
+ break;
+ }
+ return node;
+}
+
+static struct device_node * __init cvm_oct_node_for_port(struct device_node *pip,
+ int interface, int port)
+{
+ struct device_node *ni, *np;
+
+ ni = cvm_oct_of_get_child(pip, interface);
+ if (!ni)
+ return NULL;
+
+ np = cvm_oct_of_get_child(ni, port);
+ of_node_put(ni);
+
+ return np;
+}
+
static int __init cvm_oct_init_module(void)
{
int num_interfaces;
int interface;
int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE;
int qos;
+ struct device_node *pip;
octeon_mdiobus_force_mod_depencency();
pr_notice("cavium-ethernet %s\n", OCTEON_ETHERNET_VERSION);
- if (OCTEON_IS_MODEL(OCTEON_CN52XX))
- cvm_oct_mac_addr_offset = 2; /* First two are the mgmt ports. */
- else if (OCTEON_IS_MODEL(OCTEON_CN56XX))
- cvm_oct_mac_addr_offset = 1; /* First one is the mgmt port. */
- else
- cvm_oct_mac_addr_offset = 0;
+ pip = of_find_node_by_path("pip");
+ if (!pip) {
+ pr_err("Error: No 'pip' in /aliases\n");
+ return -EINVAL;
+ }
cvm_oct_poll_queue = create_singlethread_workqueue("octeon-ethernet");
if (cvm_oct_poll_queue == NULL) {
@@ -688,10 +700,11 @@ static int __init cvm_oct_init_module(void)
cvmx_helper_interface_get_mode(interface);
int num_ports = cvmx_helper_ports_on_interface(interface);
int port;
+ int port_index;
- for (port = cvmx_helper_get_ipd_port(interface, 0);
+ for (port_index = 0, port = cvmx_helper_get_ipd_port(interface, 0);
port < cvmx_helper_get_ipd_port(interface, num_ports);
- port++) {
+ port_index++, port++) {
struct octeon_ethernet *priv;
struct net_device *dev =
alloc_etherdev(sizeof(struct octeon_ethernet));
@@ -702,6 +715,7 @@ static int __init cvm_oct_init_module(void)
/* Initialize the device private structure. */
priv = netdev_priv(dev);
+ priv->of_node = cvm_oct_node_for_port(pip, interface, port_index);
INIT_DELAYED_WORK(&priv->port_periodic_work,
cvm_oct_periodic_worker);
diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h
index d581925..9360e22 100644
--- a/drivers/staging/octeon/octeon-ethernet.h
+++ b/drivers/staging/octeon/octeon-ethernet.h
@@ -31,6 +31,8 @@
#ifndef OCTEON_ETHERNET_H
#define OCTEON_ETHERNET_H
+#include <linux/of.h>
+
/**
* This is the definition of the Ethernet driver's private
* driver state stored in netdev_priv(dev).
@@ -59,6 +61,7 @@ struct octeon_ethernet {
void (*poll) (struct net_device *dev);
struct delayed_work port_periodic_work;
struct work_struct port_work; /* may be unused. */
+ struct device_node *of_node;
};
int cvm_oct_free_work(void *work_queue_entry);
--
1.7.2.3
^ permalink raw reply related [flat|nested] 40+ messages in thread* [RFC PATCH v2 12/12] staging: octeon_ethernet: Convert to use device tree.
@ 2011-03-04 19:42 ` David Daney
0 siblings, 0 replies; 40+ messages in thread
From: David Daney @ 2011-03-04 19:42 UTC (permalink / raw)
To: linux-mips, ralf, devicetree-discuss, grant.likely, linux-kernel
Cc: David Daney, David S. Miller, netdev
Get MAC address and PHY connection from the device tree.
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: netdev@vger.kernel.org
---
drivers/staging/octeon/ethernet-mdio.c | 27 +++++----
drivers/staging/octeon/ethernet.c | 88 +++++++++++++++++-------------
drivers/staging/octeon/octeon-ethernet.h | 3 +
3 files changed, 69 insertions(+), 49 deletions(-)
diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c
index 0e5dab7..38a0153 100644
--- a/drivers/staging/octeon/ethernet-mdio.c
+++ b/drivers/staging/octeon/ethernet-mdio.c
@@ -27,6 +27,7 @@
#include <linux/kernel.h>
#include <linux/ethtool.h>
#include <linux/phy.h>
+#include <linux/of_mdio.h>
#include <net/dst.h>
@@ -162,22 +163,24 @@ static void cvm_oct_adjust_link(struct net_device *dev)
int cvm_oct_phy_setup_device(struct net_device *dev)
{
struct octeon_ethernet *priv = netdev_priv(dev);
+ struct device_node *phy_node;
- int phy_addr = cvmx_helper_board_get_mii_address(priv->port);
- if (phy_addr != -1) {
- char phy_id[20];
+ if (!priv->of_node)
+ return 0;
- snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "0", phy_addr);
+ phy_node = of_parse_phandle(priv->of_node, "phy-handle", 0);
+ if (!phy_node)
+ return 0;
- priv->phydev = phy_connect(dev, phy_id, cvm_oct_adjust_link, 0,
- PHY_INTERFACE_MODE_GMII);
+ priv->phydev = of_phy_connect(dev, phy_node, cvm_oct_adjust_link, 0,
+ PHY_INTERFACE_MODE_GMII);
- if (IS_ERR(priv->phydev)) {
- priv->phydev = NULL;
- return -1;
- }
- priv->last_link = 0;
- phy_start_aneg(priv->phydev);
+ if (IS_ERR(priv->phydev)) {
+ priv->phydev = NULL;
+ return -1;
}
+ priv->last_link = 0;
+ phy_start_aneg(priv->phydev);
+
return 0;
}
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index 042adf7..16c93e4 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -31,6 +31,7 @@
#include <linux/etherdevice.h>
#include <linux/phy.h>
#include <linux/slab.h>
+#include <linux/of_net.h>
#include <net/dst.h>
@@ -112,15 +113,6 @@ int rx_napi_weight = 32;
module_param(rx_napi_weight, int, 0444);
MODULE_PARM_DESC(rx_napi_weight, "The NAPI WEIGHT parameter.");
-/*
- * The offset from mac_addr_base that should be used for the next port
- * that is configured. By convention, if any mgmt ports exist on the
- * chip, they get the first mac addresses, The ports controlled by
- * this driver are numbered sequencially following any mgmt addresses
- * that may exist.
- */
-static unsigned int cvm_oct_mac_addr_offset;
-
/**
* cvm_oct_poll_queue - Workqueue for polling operations.
*/
@@ -447,26 +439,13 @@ static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr)
int cvm_oct_common_init(struct net_device *dev)
{
struct octeon_ethernet *priv = netdev_priv(dev);
- struct sockaddr sa;
- u64 mac = ((u64)(octeon_bootinfo->mac_addr_base[0] & 0xff) << 40) |
- ((u64)(octeon_bootinfo->mac_addr_base[1] & 0xff) << 32) |
- ((u64)(octeon_bootinfo->mac_addr_base[2] & 0xff) << 24) |
- ((u64)(octeon_bootinfo->mac_addr_base[3] & 0xff) << 16) |
- ((u64)(octeon_bootinfo->mac_addr_base[4] & 0xff) << 8) |
- (u64)(octeon_bootinfo->mac_addr_base[5] & 0xff);
-
- mac += cvm_oct_mac_addr_offset;
- sa.sa_data[0] = (mac >> 40) & 0xff;
- sa.sa_data[1] = (mac >> 32) & 0xff;
- sa.sa_data[2] = (mac >> 24) & 0xff;
- sa.sa_data[3] = (mac >> 16) & 0xff;
- sa.sa_data[4] = (mac >> 8) & 0xff;
- sa.sa_data[5] = mac & 0xff;
-
- if (cvm_oct_mac_addr_offset >= octeon_bootinfo->mac_addr_count)
- printk(KERN_DEBUG "%s: Using MAC outside of the assigned range:"
- " %pM\n", dev->name, sa.sa_data);
- cvm_oct_mac_addr_offset++;
+ struct sockaddr sa = {0};
+
+ if (priv->of_node) {
+ const u8 *mac = of_get_mac_address(priv->of_node);
+ if (mac)
+ memcpy(sa.sa_data, mac, 6);
+ }
/*
* Force the interface to use the POW send if always_use_pow
@@ -594,22 +573,55 @@ static const struct net_device_ops cvm_oct_pow_netdev_ops = {
extern void octeon_mdiobus_force_mod_depencency(void);
+static struct device_node * __init cvm_oct_of_get_child(const struct device_node *parent,
+ int reg_val)
+{
+ struct device_node *node = NULL;
+ int size;
+ const __be32 *addr;
+
+ for (;;) {
+ node = of_get_next_child(parent, node);
+ if (!node)
+ break;
+ addr = of_get_property(node, "reg", &size);
+ if (addr && (be32_to_cpu(*addr) == reg_val))
+ break;
+ }
+ return node;
+}
+
+static struct device_node * __init cvm_oct_node_for_port(struct device_node *pip,
+ int interface, int port)
+{
+ struct device_node *ni, *np;
+
+ ni = cvm_oct_of_get_child(pip, interface);
+ if (!ni)
+ return NULL;
+
+ np = cvm_oct_of_get_child(ni, port);
+ of_node_put(ni);
+
+ return np;
+}
+
static int __init cvm_oct_init_module(void)
{
int num_interfaces;
int interface;
int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE;
int qos;
+ struct device_node *pip;
octeon_mdiobus_force_mod_depencency();
pr_notice("cavium-ethernet %s\n", OCTEON_ETHERNET_VERSION);
- if (OCTEON_IS_MODEL(OCTEON_CN52XX))
- cvm_oct_mac_addr_offset = 2; /* First two are the mgmt ports. */
- else if (OCTEON_IS_MODEL(OCTEON_CN56XX))
- cvm_oct_mac_addr_offset = 1; /* First one is the mgmt port. */
- else
- cvm_oct_mac_addr_offset = 0;
+ pip = of_find_node_by_path("pip");
+ if (!pip) {
+ pr_err("Error: No 'pip' in /aliases\n");
+ return -EINVAL;
+ }
cvm_oct_poll_queue = create_singlethread_workqueue("octeon-ethernet");
if (cvm_oct_poll_queue == NULL) {
@@ -688,10 +700,11 @@ static int __init cvm_oct_init_module(void)
cvmx_helper_interface_get_mode(interface);
int num_ports = cvmx_helper_ports_on_interface(interface);
int port;
+ int port_index;
- for (port = cvmx_helper_get_ipd_port(interface, 0);
+ for (port_index = 0, port = cvmx_helper_get_ipd_port(interface, 0);
port < cvmx_helper_get_ipd_port(interface, num_ports);
- port++) {
+ port_index++, port++) {
struct octeon_ethernet *priv;
struct net_device *dev =
alloc_etherdev(sizeof(struct octeon_ethernet));
@@ -702,6 +715,7 @@ static int __init cvm_oct_init_module(void)
/* Initialize the device private structure. */
priv = netdev_priv(dev);
+ priv->of_node = cvm_oct_node_for_port(pip, interface, port_index);
INIT_DELAYED_WORK(&priv->port_periodic_work,
cvm_oct_periodic_worker);
diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h
index d581925..9360e22 100644
--- a/drivers/staging/octeon/octeon-ethernet.h
+++ b/drivers/staging/octeon/octeon-ethernet.h
@@ -31,6 +31,8 @@
#ifndef OCTEON_ETHERNET_H
#define OCTEON_ETHERNET_H
+#include <linux/of.h>
+
/**
* This is the definition of the Ethernet driver's private
* driver state stored in netdev_priv(dev).
@@ -59,6 +61,7 @@ struct octeon_ethernet {
void (*poll) (struct net_device *dev);
struct delayed_work port_periodic_work;
struct work_struct port_work; /* may be unused. */
+ struct device_node *of_node;
};
int cvm_oct_free_work(void *work_queue_entry);
--
1.7.2.3
^ permalink raw reply related [flat|nested] 40+ messages in thread* Re: [RFC PATCH v2 12/12] staging: octeon_ethernet: Convert to use device tree.
2011-03-04 19:42 ` David Daney
(?)
@ 2011-03-04 21:10 ` David Miller
-1 siblings, 0 replies; 40+ messages in thread
From: David Miller @ 2011-03-04 21:10 UTC (permalink / raw)
To: ddaney
Cc: linux-mips, ralf, devicetree-discuss, grant.likely, linux-kernel,
netdev
From: David Daney <ddaney@caviumnetworks.com>
Date: Fri, 4 Mar 2011 11:42:24 -0800
> Get MAC address and PHY connection from the device tree.
>
> Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Acked-by: David S. Miller <davem@davemloft.net>
^ permalink raw reply [flat|nested] 40+ messages in thread