LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 3/3] Add PowerPC 440EPx Sequoia ehci dts entry
From: Valentine Barshak @ 2007-09-24 19:29 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-usb-devel
In-Reply-To: <20070924192519.GA4192@ru.mvista.com>

Adds USB EHCI entry to PowerPC 440EPx Sequoia DTS.

Signed-off-by: Valentine Barshak <vbarshak@ru.mvista.com>
---
 arch/powerpc/boot/dts/sequoia.dts |    8 ++++++++
 1 files changed, 8 insertions(+)

diff -ruN linux-2.6.orig/arch/powerpc/boot/dts/sequoia.dts linux-2.6/arch/powerpc/boot/dts/sequoia.dts
--- linux-2.6.orig/arch/powerpc/boot/dts/sequoia.dts	2007-09-24 14:55:15.000000000 +0400
+++ linux-2.6/arch/powerpc/boot/dts/sequoia.dts	2007-09-24 21:50:24.000000000 +0400
@@ -122,6 +122,14 @@
 			interrupt-map-mask = <ffffffff>;
 		};
 
+		USB0: ehci@e0000300 {
+			compatible = "ibm,usb-ehci-440epx", "usb-ehci";
+			interrupt-parent = <&UIC0>;
+			interrupts = <1a 4>;
+			reg = <0 e0000300 90 0 e0000390 70>;
+			big-endian;
+		};
+
 		POB0: opb {
 		  	compatible = "ibm,opb-440epx", "ibm,opb";
 			#address-cells = <1>;

^ permalink raw reply

* Re: [linux-usb-devel] [PATCH 2/3] usb: ehci-ppc-of dts bindings.
From: Valentine Barshak @ 2007-09-24 19:32 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linuxppc-dev, linux-usb-devel, David Gibson
In-Reply-To: <46F15466.6000803@ru.mvista.com>

Valentine Barshak wrote:
> Segher Boessenkool wrote:
>>>>> +  Required properties:
>>>>> +  - device_type : should be "usb".
>>>> No device_type please.  The published USB binding doesn't define
>>>> one on purpose.
>>> Could you please, explain why?
>>> Sorry, I don't think I get the concept of device description here.
>> "device_type" is meant to be used only by OF for determining the OF
>> programming model for a device.  No such thing has been defined for
>> USB busses, so the USB binding does not define a "device_type" either.
>>
>> Nothing in a flat device tree should ever define a device_type, except
>> perhaps for compatibility with legacy kernel code.
>>
>>>>> +  - compatible : should be "ehci".
>>>> Just "ehci" isn't enough -- compare to OHCI, which is the name for
>>>> a kind of USB host controller as well as for a kind of Firewire
>>>> host controller.
>>> Actually, I though device type="usb" + compatible="ehci" would be enough.
>> "compatible" values are their own namespace, you should in principle
>> be able to find a driver for a device with them without having to look
>> at other properties.
>>
>>>> Maybe "usb-ehci" is best -- can anyone think of a better name?
>>> Again, why not type="usb", compatible="ehci"?
>> Because an OF client (i.e., the Linux kernel) is not supposed to use
>> "device_type" at all for its own driver matching.
>>
>>>>> +  - interrupts : <a b> where a is the interrupt number and b is a
>>>>> +    field that represents an encoding of the sense and level
>>>>> +    information for the interrupt.
>>>> This is incorrect; not all interrupt domains use two cells, and
>>>> not all that do have this meaning for those cells.
>>> Well, this was just copied from other descriptions in 
>>> Documentation/powerpc/booting-without-of.txt
>>> Do we need to fix them all?
>> Sounds like it, yes.
>>
>>>>> +  If device registers are implemented in big endian mode, the device
>>>>> +  node should have "big-endian" property.
>>>>> +  If controller implementation operates with big endian descriptors,
>>>>> +  compatible should also have "ehci-be-desc"
>>>> Ah, I understand what this is about, finally.
>>>> Don't put this in "compatible"; instead, do a "big-endian-descriptors"
>>>> property similar to the "big-endian" property.  That last one should
>>>> maybe be "big-endian-registers" here then, to avoid confusion.
>>>> Or make "big-endian" mean both big-endian registers *and* big-endian
>>>> descriptors.
>>> But doesn't "big-endian" property actually mean "big-endian-registers"?
>>> Do we have to overload property meaning in this case?
>> It doesn't *have* a standard meaning, it is defined per device binding
>> that uses it.  Just make it mean whatever is most logical for this
>> device.
>>
>>>> I have no opinion which is best; it depends on what configurations
>>>> actually exist, and how popular those are.
>>
>> Segher
>>
> 
> OK, thanks a lot for the explanations.
> I'll modify the code.
> I think may be usb-ohci compatible values should be made properties as well,
> so that both drivers follow the same rules.
> Thanks,
> Valentine.
> 
> -------------------------------------------------------------------------
> This SF.net email is sponsored by: Microsoft
> Defy all challenges. Microsoft(R) Visual Studio 2005.
> http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
> _______________________________________________
> linux-usb-devel@lists.sourceforge.net
> To unsubscribe, use the last form field at:
> https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

I've resubmitted the patches.
(http://ozlabs.org/pipermail/linuxppc-dev/2007-September/thread.html)
Please, take a look.
Thanks,
Valentine.

^ permalink raw reply

* [PATCH 6/9] fs_enet: Be an of_platform device when CONFIG_PPC_CPM_NEW_BINDING is set.
From: Scott Wood @ 2007-09-24 20:08 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linuxppc-dev

The existing OF glue code was crufty and broken.  Rather than fix it, it
will be removed, and the ethernet driver now talks to the device tree
directly.

The old, non-CONFIG_PPC_CPM_NEW_BINDING code can go away once CPM
platforms are dropped from arch/ppc (which will hopefully be soon), and
existing arch/powerpc boards that I wasn't able to test on for this
patchset get converted (which should be even sooner).

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
Resent, with linux/of_platform.h instead of asm/of_platform.h

 drivers/net/fs_enet/Kconfig        |    1 +
 drivers/net/fs_enet/fs_enet-main.c |  259 ++++++++++++++++++++++++++++++++---
 drivers/net/fs_enet/fs_enet.h      |   55 +-------
 drivers/net/fs_enet/mac-fcc.c      |   89 +++++++++----
 drivers/net/fs_enet/mac-fec.c      |   19 +++-
 drivers/net/fs_enet/mac-scc.c      |   53 +++++--
 drivers/net/fs_enet/mii-bitbang.c  |  269 +++++++++++++++++++++++++++---------
 drivers/net/fs_enet/mii-fec.c      |  143 +++++++++++++++++++-
 include/linux/fs_enet_pd.h         |    5 +
 9 files changed, 714 insertions(+), 179 deletions(-)

diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig
index e27ee21..2765e49 100644
--- a/drivers/net/fs_enet/Kconfig
+++ b/drivers/net/fs_enet/Kconfig
@@ -11,6 +11,7 @@ config FS_ENET_HAS_SCC
 config FS_ENET_HAS_FCC
 	bool "Chip has an FCC usable for ethernet"
 	depends on FS_ENET && CPM2
+	select MDIO_BITBANG
 	default y
 
 config FS_ENET_HAS_FEC
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index a4b76cd..c5abdea 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -44,12 +44,18 @@
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+#include <linux/of_platform.h>
+#endif
+
 #include "fs_enet.h"
 
 /*************************************************/
 
+#ifndef CONFIG_PPC_CPM_NEW_BINDING
 static char version[] __devinitdata =
     DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")" "\n";
+#endif
 
 MODULE_AUTHOR("Pantelis Antoniou <panto@intracom.gr>");
 MODULE_DESCRIPTION("Freescale Ethernet Driver");
@@ -953,6 +959,7 @@ static int fs_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 extern int fs_mii_connect(struct net_device *dev);
 extern void fs_mii_disconnect(struct net_device *dev);
 
+#ifndef CONFIG_PPC_CPM_NEW_BINDING
 static struct net_device *fs_init_instance(struct device *dev,
 		struct fs_platform_info *fpi)
 {
@@ -1132,6 +1139,7 @@ static int fs_cleanup_instance(struct net_device *ndev)
 
 	return 0;
 }
+#endif
 
 /**************************************************************************************/
 
@@ -1140,35 +1148,250 @@ void *fs_enet_immap = NULL;
 
 static int setup_immap(void)
 {
-	phys_addr_t paddr = 0;
-	unsigned long size = 0;
-
 #ifdef CONFIG_CPM1
-	paddr = IMAP_ADDR;
-	size = 0x10000;	/* map 64K */
-#endif
-
-#ifdef CONFIG_CPM2
-	paddr = CPM_MAP_ADDR;
-	size = 0x40000;	/* map 256 K */
+	fs_enet_immap = ioremap(IMAP_ADDR, 0x4000);
+	WARN_ON(!fs_enet_immap);
+#elif defined(CONFIG_CPM2)
+	fs_enet_immap = cpm2_immr;
 #endif
-	fs_enet_immap = ioremap(paddr, size);
-	if (fs_enet_immap == NULL)
-		return -EBADF;	/* XXX ahem; maybe just BUG_ON? */
 
 	return 0;
 }
 
 static void cleanup_immap(void)
 {
-	if (fs_enet_immap != NULL) {
-		iounmap(fs_enet_immap);
-		fs_enet_immap = NULL;
-	}
+#if defined(CONFIG_CPM1)
+	iounmap(fs_enet_immap);
+#endif
 }
 
 /**************************************************************************************/
 
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+static int __devinit find_phy(struct device_node *np,
+                              struct fs_platform_info *fpi)
+{
+	struct device_node *phynode, *mdionode;
+	struct resource res;
+	int ret = 0, len;
+
+	const u32 *data = of_get_property(np, "phy-handle", &len);
+	if (!data || len != 4)
+		return -EINVAL;
+
+	phynode = of_find_node_by_phandle(*data);
+	if (!phynode)
+		return -EINVAL;
+
+	mdionode = of_get_parent(phynode);
+	if (!phynode)
+		goto out_put_phy;
+
+	ret = of_address_to_resource(mdionode, 0, &res);
+	if (ret)
+		goto out_put_mdio;
+
+	data = of_get_property(phynode, "reg", &len);
+	if (!data || len != 4)
+		goto out_put_mdio;
+
+	snprintf(fpi->bus_id, 16, PHY_ID_FMT, res.start, *data);
+
+out_put_mdio:
+	of_node_put(mdionode);
+out_put_phy:
+	of_node_put(phynode);
+	return ret;
+}
+
+#ifdef CONFIG_FS_ENET_HAS_FEC
+#define IS_FEC(match) ((match)->data == &fs_fec_ops)
+#else
+#define IS_FEC(match) 0
+#endif
+
+static int __devinit fs_enet_probe(struct of_device *ofdev,
+                                   const struct of_device_id *match)
+{
+	struct net_device *ndev;
+	struct fs_enet_private *fep;
+	struct fs_platform_info *fpi;
+	const u32 *data;
+	const u8 *mac_addr;
+	int privsize, len, ret = -ENODEV;
+
+	fpi = kzalloc(sizeof(*fpi), GFP_KERNEL);
+	if (!fpi)
+		return -ENOMEM;
+
+	if (!IS_FEC(match)) {
+		data = of_get_property(ofdev->node, "fsl,cpm-command", &len);
+		if (!data || len != 4)
+			goto out_free_fpi;
+
+		fpi->cp_command = *data;
+	}
+
+	fpi->rx_ring = 32;
+	fpi->tx_ring = 32;
+	fpi->rx_copybreak = 240;
+	fpi->use_napi = 0;
+	fpi->napi_weight = 17;
+
+	ret = find_phy(ofdev->node, fpi);
+	if (ret)
+		goto out_free_fpi;
+
+	privsize = sizeof(*fep) +
+	           sizeof(struct sk_buff **) *
+	           (fpi->rx_ring + fpi->tx_ring);
+
+	ndev = alloc_etherdev(privsize);
+	if (!ndev) {
+		ret = -ENOMEM;
+		goto out_free_fpi;
+	}
+
+	SET_MODULE_OWNER(ndev);
+	dev_set_drvdata(&ofdev->dev, ndev);
+
+	fep = netdev_priv(ndev);
+	fep->dev = &ofdev->dev;
+	fep->fpi = fpi;
+	fep->ops = match->data;
+
+	ret = fep->ops->setup_data(ndev);
+	if (ret)
+		goto out_free_dev;
+
+	fep->rx_skbuff = (struct sk_buff **)&fep[1];
+	fep->tx_skbuff = fep->rx_skbuff + fpi->rx_ring;
+
+	spin_lock_init(&fep->lock);
+	spin_lock_init(&fep->tx_lock);
+
+	mac_addr = of_get_mac_address(ofdev->node);
+	if (mac_addr)
+		memcpy(ndev->dev_addr, mac_addr, 6);
+
+	ret = fep->ops->allocate_bd(ndev);
+	if (ret)
+		goto out_cleanup_data;
+
+	fep->rx_bd_base = fep->ring_base;
+	fep->tx_bd_base = fep->rx_bd_base + fpi->rx_ring;
+
+	fep->tx_ring = fpi->tx_ring;
+	fep->rx_ring = fpi->rx_ring;
+
+	ndev->open = fs_enet_open;
+	ndev->hard_start_xmit = fs_enet_start_xmit;
+	ndev->tx_timeout = fs_timeout;
+	ndev->watchdog_timeo = 2 * HZ;
+	ndev->stop = fs_enet_close;
+	ndev->get_stats = fs_enet_get_stats;
+	ndev->set_multicast_list = fs_set_multicast_list;
+	if (fpi->use_napi) {
+		ndev->poll = fs_enet_rx_napi;
+		ndev->weight = fpi->napi_weight;
+	}
+	ndev->ethtool_ops = &fs_ethtool_ops;
+	ndev->do_ioctl = fs_ioctl;
+
+	init_timer(&fep->phy_timer_list);
+
+	netif_carrier_off(ndev);
+
+	ret = register_netdev(ndev);
+	if (ret)
+		goto out_free_bd;
+
+	printk(KERN_INFO "%s: fs_enet: %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       ndev->name,
+	       ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
+	       ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
+
+	return 0;
+
+out_free_bd:
+	fep->ops->free_bd(ndev);
+out_cleanup_data:
+	fep->ops->cleanup_data(ndev);
+out_free_dev:
+	free_netdev(ndev);
+	dev_set_drvdata(&ofdev->dev, NULL);
+out_free_fpi:
+	kfree(fpi);
+	return ret;
+}
+
+static int fs_enet_remove(struct of_device *ofdev)
+{
+	struct net_device *ndev = dev_get_drvdata(&ofdev->dev);
+	struct fs_enet_private *fep = netdev_priv(ndev);
+
+	unregister_netdev(ndev);
+
+	fep->ops->free_bd(ndev);
+	fep->ops->cleanup_data(ndev);
+	dev_set_drvdata(fep->dev, NULL);
+
+	free_netdev(ndev);
+	return 0;
+}
+
+static struct of_device_id fs_enet_match[] = {
+#ifdef CONFIG_FS_ENET_HAS_SCC
+	{
+		.compatible = "fsl,cpm1-scc-enet",
+		.data = (void *)&fs_scc_ops,
+	},
+#endif
+#ifdef CONFIG_FS_ENET_HAS_FCC
+	{
+		.compatible = "fsl,cpm2-fcc-enet",
+		.data = (void *)&fs_fcc_ops,
+	},
+#endif
+#ifdef CONFIG_FS_ENET_HAS_FEC
+	{
+		.compatible = "fsl,pq1-fec-enet",
+		.data = (void *)&fs_fec_ops,
+	},
+#endif
+	{}
+};
+
+static struct of_platform_driver fs_enet_driver = {
+	.name	= "fs_enet",
+	.match_table = fs_enet_match,
+	.probe = fs_enet_probe,
+	.remove = fs_enet_remove,
+};
+
+static int __init fs_init(void)
+{
+	int r = setup_immap();
+	if (r != 0)
+		return r;
+
+	r = of_register_platform_driver(&fs_enet_driver);
+	if (r != 0)
+		goto out;
+
+	return 0;
+
+out:
+	cleanup_immap();
+	return r;
+}
+
+static void __exit fs_cleanup(void)
+{
+	of_unregister_platform_driver(&fs_enet_driver);
+	cleanup_immap();
+}
+#else
 static int __devinit fs_enet_probe(struct device *dev)
 {
 	struct net_device *ndev;
@@ -1282,7 +1505,7 @@ static void __exit fs_cleanup(void)
 	driver_unregister(&fs_enet_scc_driver);
 	cleanup_immap();
 }
-
+#endif
 /**************************************************************************************/
 
 module_init(fs_init);
diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h
index f8c7ee8..14ebba8 100644
--- a/drivers/net/fs_enet/fs_enet.h
+++ b/drivers/net/fs_enet/fs_enet.h
@@ -24,19 +24,6 @@ struct fec_info {
 #include <asm/cpm2.h>
 #endif
 
-/* This is used to operate with pins.
-  Note that the actual port size may
-    be different; cpm(s) handle it OK  */
-struct bb_info {
-	u8 mdio_dat_msk;
-	u8 mdio_dir_msk;
-	u8 *mdio_dir;
-	u8 *mdio_dat;
-	u8 mdc_msk;
-	u8 *mdc_dat;
-	int delay;
-};
-
 /* hw driver ops */
 struct fs_ops {
 	int (*setup_data)(struct net_device *dev);
@@ -85,47 +72,11 @@ struct phy_info {
 #define ENET_RX_ALIGN  16
 #define ENET_RX_FRSIZE L1_CACHE_ALIGN(PKT_MAXBUF_SIZE + ENET_RX_ALIGN - 1)
 
-struct fs_enet_mii_bus {
-	struct list_head list;
-	spinlock_t mii_lock;
-	const struct fs_mii_bus_info *bus_info;
-	int refs;
-	u32 usage_map;
-
-	int (*mii_read)(struct fs_enet_mii_bus *bus,
-			int phy_id, int location);
-
-	void (*mii_write)(struct fs_enet_mii_bus *bus,
-			int phy_id, int location, int value);
-
-	union {
-		struct {
-			unsigned int mii_speed;
-			void *fecp;
-		} fec;
-
-		struct {
-			/* note that the actual port size may */
-			/* be different; cpm(s) handle it OK  */
-			u8 mdio_msk;
-			u8 *mdio_dir;
-			u8 *mdio_dat;
-			u8 mdc_msk;
-			u8 *mdc_dir;
-			u8 *mdc_dat;
-		} bitbang;
-
-		struct {
-			u16 lpa;
-		} fixed;
-	};
-};
-
 struct fs_enet_private {
 	struct device *dev;	/* pointer back to the device (must be initialized first) */
 	spinlock_t lock;	/* during all ops except TX pckt processing */
 	spinlock_t tx_lock;	/* during fs_start_xmit and fs_tx         */
-	const struct fs_platform_info *fpi;
+	struct fs_platform_info *fpi;
 	const struct fs_ops *ops;
 	int rx_ring, tx_ring;
 	dma_addr_t ring_mem_addr;
@@ -144,7 +95,6 @@ struct fs_enet_private {
 	u32 msg_enable;
 	struct mii_if_info mii_if;
 	unsigned int last_mii_status;
-	struct fs_enet_mii_bus *mii_bus;
 	int interrupt;
 
 	struct phy_device *phydev;
@@ -186,9 +136,10 @@ struct fs_enet_private {
 };
 
 /***************************************************************************/
+#ifndef CONFIG_PPC_CPM_NEW_BINDING
 int fs_enet_mdio_bb_init(void);
-int fs_mii_fixed_init(struct fs_enet_mii_bus *bus);
 int fs_enet_mdio_fec_init(void);
+#endif
 
 void fs_init_bds(struct net_device *dev);
 void fs_cleanup_bds(struct net_device *dev);
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c
index 8b30361..dc943fd 100644
--- a/drivers/net/fs_enet/mac-fcc.c
+++ b/drivers/net/fs_enet/mac-fcc.c
@@ -42,6 +42,10 @@
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+#include <linux/of_device.h>
+#endif
+
 #include "fs_enet.h"
 
 /*************************************************/
@@ -74,33 +78,64 @@
 
 #define MAX_CR_CMD_LOOPS	10000
 
-static inline int fcc_cr_cmd(struct fs_enet_private *fep, u32 mcn, u32 op)
+static inline int fcc_cr_cmd(struct fs_enet_private *fep, u32 op)
 {
 	const struct fs_platform_info *fpi = fep->fpi;
 	cpm2_map_t *immap = fs_enet_immap;
 	cpm_cpm2_t *cpmp = &immap->im_cpm;
-	u32 v;
 	int i;
 
-	/* Currently I don't know what feature call will look like. But 
-	   I guess there'd be something like do_cpm_cmd() which will require page & sblock */
-	v = mk_cr_cmd(fpi->cp_page, fpi->cp_block, mcn, op);
-	W32(cpmp, cp_cpcr, v | CPM_CR_FLG);
+	W32(cpmp, cp_cpcr, fpi->cp_command | op | CPM_CR_FLG);
 	for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
 		if ((R32(cpmp, cp_cpcr) & CPM_CR_FLG) == 0)
-			break;
-
-	if (i >= MAX_CR_CMD_LOOPS) {
-		printk(KERN_ERR "%s(): Not able to issue CPM command\n",
-		       __FUNCTION__);
-		return 1;
-	}
+			return 0;
 
-	return 0;
+	printk(KERN_ERR "%s(): Not able to issue CPM command\n",
+	       __FUNCTION__);
+	return 1;
 }
 
 static int do_pd_setup(struct fs_enet_private *fep)
 {
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+	struct of_device *ofdev = to_of_device(fep->dev);
+	struct fs_platform_info *fpi = fep->fpi;
+	int ret = -EINVAL;
+
+	fep->interrupt = of_irq_to_resource(ofdev->node, 0, NULL);
+	if (fep->interrupt == NO_IRQ)
+		goto out;
+
+	fep->fcc.fccp = of_iomap(ofdev->node, 0);
+	if (!fep->fcc.fccp)
+		goto out;
+
+	fep->fcc.ep = of_iomap(ofdev->node, 1);
+	if (!fep->fcc.ep)
+		goto out_fccp;
+
+	fep->fcc.fcccp = of_iomap(ofdev->node, 2);
+	if (!fep->fcc.fcccp)
+		goto out_ep;
+
+	fep->fcc.mem = (void *)cpm_dpalloc(128, 8);
+	fpi->dpram_offset = (u32)cpm2_immr;
+	if (IS_ERR_VALUE(fpi->dpram_offset)) {
+		ret = fpi->dpram_offset;
+		goto out_fcccp;
+	}
+
+	return 0;
+
+out_fcccp:
+	iounmap(fep->fcc.fcccp);
+out_ep:
+	iounmap(fep->fcc.ep);
+out_fccp:
+	iounmap(fep->fcc.fccp);
+out:
+	return ret;
+#else
 	struct platform_device *pdev = to_platform_device(fep->dev);
 	struct resource *r;
 
@@ -138,6 +173,7 @@ static int do_pd_setup(struct fs_enet_private *fep)
 		return -EINVAL;
 
 	return 0;
+#endif
 }
 
 #define FCC_NAPI_RX_EVENT_MSK	(FCC_ENET_RXF | FCC_ENET_RXB)
@@ -148,11 +184,17 @@ static int do_pd_setup(struct fs_enet_private *fep)
 static int setup_data(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	const struct fs_platform_info *fpi = fep->fpi;
+#ifndef CONFIG_PPC_CPM_NEW_BINDING
+	struct fs_platform_info *fpi = fep->fpi;
+
+	fpi->cp_command = (fpi->cp_page << 26) |
+	                  (fpi->cp_block << 21) |
+	                  (12 << 6);
 
 	fep->fcc.idx = fs_get_fcc_index(fpi->fs_no);
 	if ((unsigned int)fep->fcc.idx >= 3)	/* max 3 FCCs */
 		return -EINVAL;
+#endif
 
 	if (do_pd_setup(fep) != 0)
 		return -EINVAL;
@@ -226,7 +268,7 @@ static void set_multicast_one(struct net_device *dev, const u8 *mac)
 	W16(ep, fen_taddrh, taddrh);
 	W16(ep, fen_taddrm, taddrm);
 	W16(ep, fen_taddrl, taddrl);
-	fcc_cr_cmd(fep, 0x0C, CPM_CR_SET_GADDR);
+	fcc_cr_cmd(fep, CPM_CR_SET_GADDR);
 }
 
 static void set_multicast_finish(struct net_device *dev)
@@ -281,7 +323,7 @@ static void restart(struct net_device *dev)
 
 	/* clear everything (slow & steady does it) */
 	for (i = 0; i < sizeof(*ep); i++)
-		out_8((char *)ep + i, 0);
+		out_8((u8 __iomem *)ep + i, 0);
 
 	/* get physical address */
 	rx_bd_base_phys = fep->ring_mem_addr;
@@ -397,7 +439,7 @@ static void restart(struct net_device *dev)
 			S8(fcccp, fcc_gfemr, 0x20);
 	}
 
-	fcc_cr_cmd(fep, 0x0c, CPM_CR_INIT_TRX);
+	fcc_cr_cmd(fep, CPM_CR_INIT_TRX);
 
 	/* clear events */
 	W16(fccp, fcc_fcce, 0xffff);
@@ -515,23 +557,22 @@ int get_regs(struct net_device *dev, void *p, int *sizep)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
 
-	if (*sizep < sizeof(fcc_t) + sizeof(fcc_c_t) + sizeof(fcc_enet_t))
+	if (*sizep < sizeof(fcc_t) + sizeof(fcc_enet_t) + 1)
 		return -EINVAL;
 
 	memcpy_fromio(p, fep->fcc.fccp, sizeof(fcc_t));
 	p = (char *)p + sizeof(fcc_t);
 
-	memcpy_fromio(p, fep->fcc.fcccp, sizeof(fcc_c_t));
-	p = (char *)p + sizeof(fcc_c_t);
-
 	memcpy_fromio(p, fep->fcc.ep, sizeof(fcc_enet_t));
+	p = (char *)p + sizeof(fcc_enet_t);
 
+	memcpy_fromio(p, fep->fcc.fcccp, 1);
 	return 0;
 }
 
 int get_regs_len(struct net_device *dev)
 {
-	return sizeof(fcc_t) + sizeof(fcc_c_t) + sizeof(fcc_enet_t);
+	return sizeof(fcc_t) + sizeof(fcc_enet_t) + 1;
 }
 
 /* Some transmit errors cause the transmitter to shut
@@ -551,7 +592,7 @@ void tx_restart(struct net_device *dev)
 	udelay(10);
 	S32(fccp, fcc_gfmr, FCC_GFMR_ENT);
 
-	fcc_cr_cmd(fep, 0x0C, CPM_CR_RESTART_TX);
+	fcc_cr_cmd(fep, CPM_CR_RESTART_TX);
 }
 
 /*************************************************************************/
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index 04b4f80..7477da0 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -43,6 +43,10 @@
 #include <asm/commproc.h>
 #endif
 
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+#include <linux/of_device.h>
+#endif
+
 #include "fs_enet.h"
 #include "fec.h"
 
@@ -95,6 +99,19 @@ static int whack_reset(fec_t * fecp)
 
 static int do_pd_setup(struct fs_enet_private *fep)
 {
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+	struct of_device *ofdev = to_of_device(fep->dev);
+
+	fep->interrupt = of_irq_to_resource(ofdev->node, 0, NULL);
+	if (fep->interrupt == NO_IRQ)
+		return -EINVAL;
+
+	fep->fec.fecp = of_iomap(ofdev->node, 0);
+	if (!fep->fcc.fccp)
+		return -EINVAL;
+
+	return 0;
+#else
 	struct platform_device *pdev = to_platform_device(fep->dev); 
 	struct resource	*r;
 	
@@ -110,7 +127,7 @@ static int do_pd_setup(struct fs_enet_private *fep)
 		return -EINVAL;
 
 	return 0;
-	
+#endif
 }
 
 #define FEC_NAPI_RX_EVENT_MSK	(FEC_ENET_RXF | FEC_ENET_RXB)
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c
index 7540966..59e0d1d 100644
--- a/drivers/net/fs_enet/mac-scc.c
+++ b/drivers/net/fs_enet/mac-scc.c
@@ -43,6 +43,10 @@
 #include <asm/commproc.h>
 #endif
 
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+#include <linux/of_platform.h>
+#endif
+
 #include "fs_enet.h"
 
 /*************************************************/
@@ -89,27 +93,38 @@
 
 static inline int scc_cr_cmd(struct fs_enet_private *fep, u32 op)
 {
-	cpm8xx_t *cpmp = &((immap_t *)fs_enet_immap)->im_cpm;
-	u32 v, ch;
-	int i = 0;
+	const struct fs_platform_info *fpi = fep->fpi;
+	int i;
 
-	ch = fep->scc.idx << 2;
-	v = mk_cr_cmd(ch, op);
-	W16(cpmp, cp_cpcr, v | CPM_CR_FLG);
+	W16(cpmp, cp_cpcr, fpi->cp_command | CPM_CR_FLG | (op << 8));
 	for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
 		if ((R16(cpmp, cp_cpcr) & CPM_CR_FLG) == 0)
-			break;
+			return 0;
 
-	if (i >= MAX_CR_CMD_LOOPS) {
-		printk(KERN_ERR "%s(): Not able to issue CPM command\n",
-			__FUNCTION__);
-		return 1;
-	}
-	return 0;
+	printk(KERN_ERR "%s(): Not able to issue CPM command\n",
+		__FUNCTION__);
+	return 1;
 }
 
 static int do_pd_setup(struct fs_enet_private *fep)
 {
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+	struct of_device *ofdev = to_of_device(fep->dev);
+
+	fep->interrupt = of_irq_to_resource(ofdev->node, 0, NULL);
+	if (fep->interrupt == NO_IRQ)
+		return -EINVAL;
+
+	fep->scc.sccp = of_iomap(ofdev->node, 0);
+	if (!fep->scc.sccp)
+		return -EINVAL;
+
+	fep->scc.ep = of_iomap(ofdev->node, 1);
+	if (!fep->scc.ep) {
+		iounmap(fep->scc.sccp);
+		return -EINVAL;
+	}
+#else
 	struct platform_device *pdev = to_platform_device(fep->dev);
 	struct resource *r;
 
@@ -129,6 +144,7 @@ static int do_pd_setup(struct fs_enet_private *fep)
 
 	if (fep->scc.ep == NULL)
 		return -EINVAL;
+#endif
 
 	return 0;
 }
@@ -141,12 +157,17 @@ static int do_pd_setup(struct fs_enet_private *fep)
 static int setup_data(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	const struct fs_platform_info *fpi = fep->fpi;
+
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+	struct fs_platform_info *fpi = fep->fpi;
 
 	fep->scc.idx = fs_get_scc_index(fpi->fs_no);
-	if ((unsigned int)fep->fcc.idx > 4)	/* max 4 SCCs */
+	if ((unsigned int)fep->fcc.idx >= 4) /* max 4 SCCs */
 		return -EINVAL;
 
+	fpi->cp_command = fep->fcc.idx << 6;
+#endif
+
 	do_pd_setup(fep);
 
 	fep->scc.hthi = 0;
@@ -154,7 +175,7 @@ static int setup_data(struct net_device *dev)
 
 	fep->ev_napi_rx = SCC_NAPI_RX_EVENT_MSK;
 	fep->ev_rx = SCC_RX_EVENT;
-	fep->ev_tx = SCC_TX_EVENT;
+	fep->ev_tx = SCC_TX_EVENT | SCCE_ENET_TXE;
 	fep->ev_err = SCC_ERR_EVENT_MSK;
 
 	return 0;
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
index 8f766a5..2b9c44c 100644
--- a/drivers/net/fs_enet/mii-bitbang.c
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -13,11 +13,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ptrace.h>
-#include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
@@ -25,86 +20,77 @@
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/bitops.h>
 #include <linux/platform_device.h>
 
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+#include <linux/of_platform.h>
+#endif
 
 #include "fs_enet.h"
 
-static int bitbang_prep_bit(u8 **datp, u8 *mskp,
-		struct fs_mii_bit *mii_bit)
-{
-	void *dat;
-	int adv;
-	u8 msk;
-
-	dat = (void*) mii_bit->offset;
-
-	adv = mii_bit->bit >> 3;
-	dat = (char *)dat + adv;
-
-	msk = 1 << (7 - (mii_bit->bit & 7));
-
-	*datp = dat;
-	*mskp = msk;
-
-	return 0;
-}
+struct bb_info {
+	__be32 __iomem *dir;
+	__be32 __iomem *dat;
+	u32 mdio_msk;
+	u32 mdc_msk;
+	int delay;
+};
 
-static inline void bb_set(u8 *p, u8 m)
+/* FIXME: If any other users of GPIO crop up, then these will have to
+ * have some sort of global synchronization to avoid races with other
+ * pins on the same port.  The ideal solution would probably be to
+ * bind the ports to a GPIO driver, and have this be a client of it.
+ */
+static inline void bb_set(u32 __iomem *p, u32 m)
 {
-	out_8(p, in_8(p) | m);
+	out_be32(p, in_be32(p) | m);
 }
 
-static inline void bb_clr(u8 *p, u8 m)
+static inline void bb_clr(u32 __iomem *p, u32 m)
 {
-	out_8(p, in_8(p) & ~m);
+	out_be32(p, in_be32(p) & ~m);
 }
 
-static inline int bb_read(u8 *p, u8 m)
+static inline int bb_read(u32 __iomem *p, u32 m)
 {
-	return (in_8(p) & m) != 0;
+	return (in_be32(p) & m) != 0;
 }
 
 static inline void mdio_active(struct bb_info *bitbang)
 {
-	bb_set(bitbang->mdio_dir, bitbang->mdio_dir_msk);
+	bb_set(bitbang->dir, bitbang->mdio_msk);
 }
 
-static inline void mdio_tristate(struct bb_info *bitbang )
+static inline void mdio_tristate(struct bb_info *bitbang)
 {
-	bb_clr(bitbang->mdio_dir, bitbang->mdio_dir_msk);
+	bb_clr(bitbang->dir, bitbang->mdio_msk);
 }
 
-static inline int mdio_read(struct bb_info *bitbang )
+static inline int mdio_read(struct bb_info *bitbang)
 {
-	return bb_read(bitbang->mdio_dat, bitbang->mdio_dat_msk);
+	return bb_read(bitbang->dat, bitbang->mdio_msk);
 }
 
-static inline void mdio(struct bb_info *bitbang , int what)
+static inline void mdio(struct bb_info *bitbang, int what)
 {
 	if (what)
-		bb_set(bitbang->mdio_dat, bitbang->mdio_dat_msk);
+		bb_set(bitbang->dat, bitbang->mdio_msk);
 	else
-		bb_clr(bitbang->mdio_dat, bitbang->mdio_dat_msk);
+		bb_clr(bitbang->dat, bitbang->mdio_msk);
 }
 
-static inline void mdc(struct bb_info *bitbang , int what)
+static inline void mdc(struct bb_info *bitbang, int what)
 {
 	if (what)
-		bb_set(bitbang->mdc_dat, bitbang->mdc_msk);
+		bb_set(bitbang->dat, bitbang->mdc_msk);
 	else
-		bb_clr(bitbang->mdc_dat, bitbang->mdc_msk);
+		bb_clr(bitbang->dat, bitbang->mdc_msk);
 }
 
-static inline void mii_delay(struct bb_info *bitbang )
+static inline void mii_delay(struct bb_info *bitbang)
 {
 	udelay(bitbang->delay);
 }
@@ -280,29 +266,178 @@ static int fs_enet_mii_bb_reset(struct mii_bus *bus)
 	return 0;
 }
 
-static int fs_mii_bitbang_init(struct bb_info *bitbang, struct fs_mii_bb_platform_info* fmpi)
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
+                                         struct device_node *np)
 {
-	int r;
+	struct resource res;
+	const u32 *data;
+	int mdio_pin, mdc_pin, len;
+	struct bb_info *bitbang = bus->priv;
 
-	bitbang->delay = fmpi->delay;
+	int ret = of_address_to_resource(np, 0, &res);
+	if (ret)
+		return ret;
+
+	if (res.end - res.start < 13)
+		return -ENODEV;
+
+	/* This should really encode the pin number as well, but all
+	 * we get is an int, and the odds of multiple bitbang mdio buses
+	 * is low enough that it's not worth going too crazy.
+	 */
+	bus->id = res.start;
+
+	data = of_get_property(np, "fsl,mdio-pin", &len);
+	if (!data || len != 4)
+		return -ENODEV;
+	mdio_pin = *data;
+
+	data = of_get_property(np, "fsl,mdc-pin", &len);
+	if (!data || len != 4)
+		return -ENODEV;
+	mdc_pin = *data;
+
+	bitbang->dir = ioremap(res.start, res.end - res.start + 1);
+	if (!bitbang->dir)
+		return -ENOMEM;
+
+	bitbang->dat = bitbang->dir + 4;
+	bitbang->mdio_msk = 1 << (31 - mdio_pin);
+	bitbang->mdc_msk = 1 << (31 - mdc_pin);
+	bitbang->delay = 1; /* 1 us between operations */
 
-	r = bitbang_prep_bit(&bitbang->mdio_dir,
-			 &bitbang->mdio_dir_msk,
-			 &fmpi->mdio_dir);
-	if (r != 0)
-		return r;
-
-	r = bitbang_prep_bit(&bitbang->mdio_dat,
-			 &bitbang->mdio_dat_msk,
-			 &fmpi->mdio_dat);
-	if (r != 0)
-		return r;
-
-	r = bitbang_prep_bit(&bitbang->mdc_dat,
-			 &bitbang->mdc_msk,
-			 &fmpi->mdc_dat);
-	if (r != 0)
-		return r;
+	return 0;
+}
+
+static void __devinit add_phy(struct mii_bus *bus, struct device_node *np)
+{
+	const u32 *data;
+	int len, id, irq;
+
+	data = of_get_property(np, "reg", &len);
+	if (!data || len != 4)
+		return;
+
+	id = *data;
+	bus->phy_mask &= ~(1 << id);
+
+	irq = of_irq_to_resource(np, 0, NULL);
+	if (irq != NO_IRQ)
+		bus->irq[id] = irq;
+}
+
+static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
+                                        const struct of_device_id *match)
+{
+	struct device_node *np = NULL;
+	struct mii_bus *new_bus;
+	struct bb_info *bitbang;
+	int ret = -ENOMEM;
+	int i;
+
+	new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
+	if (!new_bus)
+		goto out;
+
+	bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
+	if (!bitbang)
+		goto out_free_bus;
+
+	new_bus->priv = bitbang;
+	new_bus->name = "CPM2 Bitbanged MII",
+	new_bus->read = &fs_enet_mii_bb_read,
+	new_bus->write = &fs_enet_mii_bb_write,
+	new_bus->reset = &fs_enet_mii_bb_reset,
+
+	ret = fs_mii_bitbang_init(new_bus, ofdev->node);
+	if (ret)
+		goto out_free_bitbang;
+
+	new_bus->phy_mask = ~0;
+	new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+	if (!new_bus->irq)
+		goto out_unmap_regs;
+
+	for (i = 0; i < PHY_MAX_ADDR; i++)
+		new_bus->irq[i] = -1;
+
+	while ((np = of_get_next_child(ofdev->node, np)))
+		if (!strcmp(np->type, "ethernet-phy"))
+			add_phy(new_bus, np);
+
+	new_bus->dev = &ofdev->dev;
+	dev_set_drvdata(&ofdev->dev, new_bus);
+
+	ret = mdiobus_register(new_bus);
+	if (ret)
+		goto out_free_irqs;
+
+	return 0;
+
+out_free_irqs:
+	dev_set_drvdata(&ofdev->dev, NULL);
+	kfree(new_bus->irq);
+out_unmap_regs:
+	iounmap(bitbang->dir);
+out_free_bitbang:
+	kfree(bitbang);
+out_free_bus:
+	kfree(new_bus);
+out:
+	return ret;
+}
+
+static int fs_enet_mdio_remove(struct of_device *ofdev)
+{
+	struct mii_bus *bus = dev_get_drvdata(&ofdev->dev);
+	struct bb_info *bitbang = bus->priv;
+
+	mdiobus_unregister(bus);
+	dev_set_drvdata(&ofdev->dev, NULL);
+	kfree(bus->irq);
+	iounmap(bitbang->dir);
+	kfree(bitbang);
+	kfree(bus);
+
+	return 0;
+}
+
+static struct of_device_id fs_enet_mdio_bb_match[] = {
+	{
+		.compatible = "fsl,cpm2-mdio-bitbang",
+	},
+	{},
+};
+
+static struct of_platform_driver fs_enet_bb_mdio_driver = {
+	.name = "fsl-bb-mdio",
+	.match_table = fs_enet_mdio_bb_match,
+	.probe = fs_enet_mdio_probe,
+	.remove = fs_enet_mdio_remove,
+};
+
+int fs_enet_mdio_bb_init(void)
+{
+	return of_register_platform_driver(&fs_enet_bb_mdio_driver);
+}
+
+void fs_enet_mdio_bb_exit(void)
+{
+	of_unregister_platform_driver(&fs_enet_bb_mdio_driver);
+}
+
+module_init(fs_enet_mdio_bb_init);
+module_exit(fs_enet_mdio_bb_exit);
+#else
+static int __devinit fs_mii_bitbang_init(struct bb_info *bitbang,
+                                         struct fs_mii_bb_platform_info *fmpi)
+{
+	bitbang->dir = (u32 __iomem *)fmpi->mdio_dir.offset;
+	bitbang->dat = (u32 __iomem *)fmpi->mdio_dat.offset;
+	bitbang->mdio_msk = 1U << (31 - fmpi->mdio_dat.bit);
+	bitbang->mdc_msk = 1U << (31 - fmpi->mdc_dat.bit);
+	bitbang->delay = fmpi->delay;
 
 	return 0;
 }
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
index 53db696..07b6f20 100644
--- a/drivers/net/fs_enet/mii-fec.c
+++ b/drivers/net/fs_enet/mii-fec.c
@@ -36,6 +36,10 @@
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+#include <linux/of_platform.h>
+#endif
+
 #include "fs_enet.h"
 #include "fec.h"
 
@@ -47,6 +51,7 @@
 
 #define FEC_MII_LOOPS	10000
 
+#ifndef CONFIG_PPC_CPM_NEW_BINDING
 static int match_has_phy (struct device *dev, void* data)
 {
 	struct platform_device* pdev = container_of(dev, struct platform_device, dev);
@@ -90,6 +95,7 @@ static int fs_mii_fec_init(struct fec_info* fec, struct fs_mii_fec_platform_info
 
 	return 0;
 }
+#endif
 
 static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location)
 {
@@ -145,6 +151,141 @@ static int fs_enet_fec_mii_reset(struct mii_bus *bus)
 	return 0;
 }
 
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+static void __devinit add_phy(struct mii_bus *bus, struct device_node *np)
+{
+	const u32 *data;
+	int len, id, irq;
+
+	data = of_get_property(np, "reg", &len);
+	if (!data || len != 4)
+		return;
+
+	id = *data;
+	bus->phy_mask &= ~(1 << id);
+
+	irq = of_irq_to_resource(np, 0, NULL);
+	if (irq != NO_IRQ)
+		bus->irq[id] = irq;
+}
+
+static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
+                                        const struct of_device_id *match)
+{
+	struct device_node *np = NULL;
+	struct resource res;
+	struct mii_bus *new_bus;
+	struct fec_info *fec;
+	int ret = -ENOMEM, i;
+
+	new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
+	if (!new_bus)
+		goto out;
+
+	fec = kzalloc(sizeof(struct fec_info), GFP_KERNEL);
+	if (!fec)
+		goto out_mii;
+
+	new_bus->priv = fec;
+	new_bus->name = "FEC MII Bus";
+	new_bus->read = &fs_enet_fec_mii_read;
+	new_bus->write = &fs_enet_fec_mii_write;
+	new_bus->reset = &fs_enet_fec_mii_reset;
+
+	ret = of_address_to_resource(ofdev->node, 0, &res);
+	if (ret)
+		return ret;
+
+	new_bus->id = res.start;
+
+	fec->fecp = ioremap(res.start, res.end - res.start + 1);
+	if (!fec->fecp)
+		goto out_fec;
+
+	fec->mii_speed = ((ppc_proc_freq + 4999999) / 5000000) << 1;
+
+	setbits32(&fec->fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
+	setbits32(&fec->fecp->fec_ecntrl, FEC_ECNTRL_PINMUX |
+	                                  FEC_ECNTRL_ETHER_EN);
+	out_be32(&fec->fecp->fec_ievent, FEC_ENET_MII);
+	out_be32(&fec->fecp->fec_mii_speed, fec->mii_speed);
+
+	new_bus->phy_mask = ~0;
+	new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+	if (!new_bus->irq)
+		goto out_unmap_regs;
+
+	for (i = 0; i < PHY_MAX_ADDR; i++)
+		new_bus->irq[i] = -1;
+
+	while ((np = of_get_next_child(ofdev->node, np)))
+		if (!strcmp(np->type, "ethernet-phy"))
+			add_phy(new_bus, np);
+
+	new_bus->dev = &ofdev->dev;
+	dev_set_drvdata(&ofdev->dev, new_bus);
+
+	ret = mdiobus_register(new_bus);
+	if (ret)
+		goto out_free_irqs;
+
+	return 0;
+
+out_free_irqs:
+	dev_set_drvdata(&ofdev->dev, NULL);
+	kfree(new_bus->irq);
+out_unmap_regs:
+	iounmap(fec->fecp);
+out_fec:
+	kfree(fec);
+out_mii:
+	kfree(new_bus);
+out:
+	return ret;
+}
+
+static int fs_enet_mdio_remove(struct of_device *ofdev)
+{
+	struct mii_bus *bus = dev_get_drvdata(&ofdev->dev);
+	struct fec_info *fec = bus->priv;
+
+	mdiobus_unregister(bus);
+	dev_set_drvdata(&ofdev->dev, NULL);
+	kfree(bus->irq);
+	iounmap(fec->fecp);
+	kfree(fec);
+	kfree(bus);
+
+	return 0;
+}
+
+static struct of_device_id fs_enet_mdio_fec_match[] = {
+	{
+		.compatible = "fsl,pq1-fec-mdio",
+	},
+	{},
+};
+
+static struct of_platform_driver fs_enet_fec_mdio_driver = {
+	.name = "fsl-fec-mdio",
+	.match_table = fs_enet_mdio_fec_match,
+	.probe = fs_enet_mdio_probe,
+	.remove = fs_enet_mdio_remove,
+};
+
+static int fs_enet_mdio_fec_init(void)
+{
+	return of_register_platform_driver(&fs_enet_fec_mdio_driver);
+}
+
+static void fs_enet_mdio_fec_exit(void)
+{
+	of_unregister_platform_driver(&fs_enet_fec_mdio_driver);
+}
+
+module_init(fs_enet_mdio_fec_init);
+module_exit(fs_enet_mdio_fec_exit);
+#else
 static int __devinit fs_enet_fec_mdio_probe(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
@@ -235,4 +376,4 @@ void fs_enet_mdio_fec_exit(void)
 {
 	driver_unregister(&fs_enet_fec_mdio_driver);
 }
-
+#endif
diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h
index 815c6f9..9bc045b 100644
--- a/include/linux/fs_enet_pd.h
+++ b/include/linux/fs_enet_pd.h
@@ -120,6 +120,7 @@ struct fs_platform_info {
 
 	u32 cp_page;		/* CPM page */
 	u32 cp_block;		/* CPM sblock */
+	u32 cp_command;		/* CPM page/sblock/mcn */
 
 	u32 clk_trx;		/* some stuff for pins & mux configuration*/
 	u32 clk_rx;
@@ -134,7 +135,11 @@ struct fs_platform_info {
 	u32 device_flags;
 
 	int phy_addr;		/* the phy address (-1 no phy) */
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+	char bus_id[16];
+#else
 	const char*	bus_id;
+#endif
 	int phy_irq;		/* the phy irq (if it exists)  */
 
 	const struct fs_mii_bus_info *bus_info;
-- 
1.5.3.1

^ permalink raw reply related

* [PATCH 15/40] bootwrapper: Factor out dt_set_mac_address().
From: Scott Wood @ 2007-09-24 20:09 UTC (permalink / raw)
  To: galak; +Cc: linuxppc-dev

This allows callers to set addresses one at a time when that would be more
convenient.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
Resent, with dt_set_mac_address -> dt-fixup_mac_address.

 arch/powerpc/boot/devtree.c |   31 +++++++++++++++++--------------
 arch/powerpc/boot/ops.h     |    1 +
 2 files changed, 18 insertions(+), 14 deletions(-)

diff --git a/arch/powerpc/boot/devtree.c b/arch/powerpc/boot/devtree.c
index 549463b..e5dfe44 100644
--- a/arch/powerpc/boot/devtree.c
+++ b/arch/powerpc/boot/devtree.c
@@ -88,29 +88,32 @@ void dt_fixup_clock(const char *path, u32 freq)
 	}
 }
 
+void dt_fixup_mac_address(u32 index, const u8 *addr)
+{
+	void *devp = find_node_by_prop_value(NULL, "linux,network-index",
+	                                     (void*)&index, sizeof(index));
+
+	if (devp) {
+		printf("ENET%d: local-mac-address <-"
+		       " %02x:%02x:%02x:%02x:%02x:%02x\n\r", index,
+		       addr[0], addr[1], addr[2],
+		       addr[3], addr[4], addr[5]);
+
+		setprop(devp, "local-mac-address", addr, 6);
+	}
+}
+
 void __dt_fixup_mac_addresses(u32 startindex, ...)
 {
 	va_list ap;
 	u32 index = startindex;
-	void *devp;
 	const u8 *addr;
 
 	va_start(ap, startindex);
-	while ((addr = va_arg(ap, const u8 *))) {
-		devp = find_node_by_prop_value(NULL, "linux,network-index",
-					       (void*)&index, sizeof(index));
 
-		if (devp) {
-			printf("ENET%d: local-mac-address <-"
-			       " %02x:%02x:%02x:%02x:%02x:%02x\n\r", index,
-			       addr[0], addr[1], addr[2],
-			       addr[3], addr[4], addr[5]);
+	while ((addr = va_arg(ap, const u8 *)))
+		dt_fixup_mac_address(index++, addr);
 
-			setprop(devp, "local-mac-address", addr, 6);
-		}
-
-		index++;
-	}
 	va_end(ap);
 }
 
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
index 703255b..5b77fe3 100644
--- a/arch/powerpc/boot/ops.h
+++ b/arch/powerpc/boot/ops.h
@@ -160,6 +160,7 @@ static inline void *find_node_by_devtype(const void *prev,
 void dt_fixup_memory(u64 start, u64 size);
 void dt_fixup_cpu_clocks(u32 cpufreq, u32 tbfreq, u32 busfreq);
 void dt_fixup_clock(const char *path, u32 freq);
+void dt_fixup_mac_address(u32 index, const u8 *addr);
 void __dt_fixup_mac_addresses(u32 startindex, ...);
 #define dt_fixup_mac_addresses(...) \
 	__dt_fixup_mac_addresses(0, __VA_ARGS__, NULL)
-- 
1.5.3.1

^ permalink raw reply related

* [PATCH 2/2] bootwrapper: Add PlanetCore firmware support.
From: Scott Wood @ 2007-09-24 20:09 UTC (permalink / raw)
  To: galak; +Cc: linuxppc-dev

This is a library that board code can use to extract information from the
PlanetCore configuration keys.  PlanetCore is used on various boards from
Embedded Planet.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
Resent, with dt_set_mac_address -> dt_fixup_mac_address.

 arch/powerpc/boot/Makefile     |    2 +-
 arch/powerpc/boot/planetcore.c |  166 ++++++++++++++++++++++++++++++++++++++++
 arch/powerpc/boot/planetcore.h |   49 ++++++++++++
 3 files changed, 216 insertions(+), 1 deletions(-)
 create mode 100644 arch/powerpc/boot/planetcore.c
 create mode 100644 arch/powerpc/boot/planetcore.h

diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index cffef14..9ec785c 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -45,7 +45,7 @@ src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
 		ns16550.c serial.c simple_alloc.c div64.S util.S \
 		gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
 		4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \
-		cpm-serial.c stdlib.c
+		cpm-serial.c stdlib.c planetcore.c
 src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \
 		cuboot-ebony.c treeboot-ebony.c prpmc2800.c \
 		ps3-head.S ps3-hvcall.S ps3.c treeboot-bamboo.c cuboot-8xx.c \
diff --git a/arch/powerpc/boot/planetcore.c b/arch/powerpc/boot/planetcore.c
new file mode 100644
index 0000000..0d8558a
--- /dev/null
+++ b/arch/powerpc/boot/planetcore.c
@@ -0,0 +1,166 @@
+/*
+ * PlanetCore configuration data support functions
+ *
+ * Author: Scott Wood <scottwood@freescale.com>
+ *
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "stdio.h"
+#include "stdlib.h"
+#include "ops.h"
+#include "planetcore.h"
+#include "io.h"
+
+/* PlanetCore passes information to the OS in the form of
+ * a table of key=value strings, separated by newlines.
+ *
+ * The list is terminated by an empty string (i.e. two
+ * consecutive newlines).
+ *
+ * To make it easier to parse, we first convert all the
+ * newlines into null bytes.
+ */
+
+void planetcore_prepare_table(char *table)
+{
+	do {
+		if (*table == '\n')
+			*table = 0;
+
+		table++;
+	} while (*(table - 1) || *table != '\n');
+
+	*table = 0;
+}
+
+const char *planetcore_get_key(const char *table, const char *key)
+{
+	int keylen = strlen(key);
+
+	do {
+		if (!strncmp(table, key, keylen) && table[keylen] == '=')
+			return table + keylen + 1;
+
+		table += strlen(table) + 1;
+	} while (strlen(table) != 0);
+
+	return NULL;
+}
+
+int planetcore_get_decimal(const char *table, const char *key, u64 *val)
+{
+	const char *str = planetcore_get_key(table, key);
+	if (!str)
+		return 0;
+
+	*val = strtoull(str, NULL, 10);
+	return 1;
+}
+
+int planetcore_get_hex(const char *table, const char *key, u64 *val)
+{
+	const char *str = planetcore_get_key(table, key);
+	if (!str)
+		return 0;
+
+	*val = strtoull(str, NULL, 16);
+	return 1;
+}
+
+static u64 mac_table[4] = {
+	0x000000000000,
+	0x000000800000,
+	0x000000400000,
+	0x000000c00000,
+};
+
+void planetcore_set_mac_addrs(const char *table)
+{
+	u8 addr[4][6];
+	u64 int_addr;
+	u32 i;
+	int j;
+
+	if (!planetcore_get_hex(table, PLANETCORE_KEY_MAC_ADDR, &int_addr))
+		return;
+
+	for (i = 0; i < 4; i++) {
+		u64 this_dev_addr = (int_addr & ~0x000000c00000) |
+		                    mac_table[i];
+
+		for (j = 5; j >= 0; j--) {
+			addr[i][j] = this_dev_addr & 0xff;
+			this_dev_addr >>= 8;
+		}
+
+		dt_fixup_mac_address(i, addr[i]);
+	}
+}
+
+static char prop_buf[MAX_PROP_LEN];
+
+void planetcore_set_stdout_path(const char *table)
+{
+	char *path;
+	const char *label;
+	void *node, *chosen;
+
+	label = planetcore_get_key(table, PLANETCORE_KEY_SERIAL_PORT);
+	if (!label)
+		return;
+
+	node = find_node_by_prop_value_str(NULL, "linux,planetcore-label",
+	                                   label);
+	if (!node)
+		return;
+
+	path = get_path(node, prop_buf, MAX_PROP_LEN);
+	if (!path)
+		return;
+
+	chosen = finddevice("/chosen");
+	if (!chosen)
+		chosen = create_node(NULL, "chosen");
+	if (!chosen)
+		return;
+
+	setprop_str(chosen, "linux,stdout-path", path);
+}
+
+void planetcore_set_serial_speed(const char *table)
+{
+	void *chosen, *stdout;
+	u64 baud;
+	u32 baud32;
+	int len;
+
+	chosen = finddevice("/chosen");
+	if (!chosen)
+		return;
+
+	len = getprop(chosen, "linux,stdout-path", prop_buf, MAX_PROP_LEN);
+	if (len <= 0)
+		return;
+
+	stdout = finddevice(prop_buf);
+	if (!stdout) {
+		printf("planetcore_set_serial_speed: "
+		       "Bad /chosen/linux,stdout-path.\r\n");
+
+		return;
+	}
+
+	if (!planetcore_get_decimal(table, PLANETCORE_KEY_SERIAL_BAUD,
+	                            &baud)) {
+		printf("planetcore_set_serial_speed: No SB tag.\r\n");
+		return;
+	}
+
+	baud32 = baud;
+	setprop(stdout, "current-speed", &baud32, 4);
+}
diff --git a/arch/powerpc/boot/planetcore.h b/arch/powerpc/boot/planetcore.h
new file mode 100644
index 0000000..0d4094f
--- /dev/null
+++ b/arch/powerpc/boot/planetcore.h
@@ -0,0 +1,49 @@
+#ifndef _PPC_BOOT_PLANETCORE_H_
+#define _PPC_BOOT_PLANETCORE_H_
+
+#include "types.h"
+
+#define PLANETCORE_KEY_BOARD_TYPE   "BO"
+#define PLANETCORE_KEY_BOARD_REV    "BR"
+#define PLANETCORE_KEY_MB_RAM       "D1"
+#define PLANETCORE_KEY_MAC_ADDR     "EA"
+#define PLANETCORE_KEY_FLASH_SPEED  "FS"
+#define PLANETCORE_KEY_IP_ADDR      "IP"
+#define PLANETCORE_KEY_KB_NVRAM     "NV"
+#define PLANETCORE_KEY_PROCESSOR    "PR"
+#define PLANETCORE_KEY_PROC_VARIANT "PV"
+#define PLANETCORE_KEY_SERIAL_BAUD  "SB"
+#define PLANETCORE_KEY_SERIAL_PORT  "SP"
+#define PLANETCORE_KEY_SWITCH       "SW"
+#define PLANETCORE_KEY_TEMP_OFFSET  "TC"
+#define PLANETCORE_KEY_TARGET_IP    "TIP"
+#define PLANETCORE_KEY_CRYSTAL_HZ   "XT"
+
+/* Prepare the table for processing, by turning all newlines
+ * into NULL bytes.
+ */
+void planetcore_prepare_table(char *table);
+
+/* Return the value associated with a given key in text,
+ * decimal, or hex format.
+ *
+ * Returns zero/NULL on failure, non-zero on success.
+ */
+const char *planetcore_get_key(const char *table, const char *key);
+int planetcore_get_decimal(const char *table, const char *key, u64 *val);
+int planetcore_get_hex(const char *table, const char *key, u64 *val);
+
+/* Updates the device tree local-mac-address properties based
+ * on the EA tag.
+ */
+void planetcore_set_mac_addrs(const char *table);
+
+/* Sets the linux,stdout-path in the /chosen node.  This requires the
+ * linux,planetcore-label property in each serial node.
+ */
+void planetcore_set_stdout_path(const char *table);
+
+/* Sets the current-speed property in the serial node. */
+void planetcore_set_serial_speed(const char *table);
+
+#endif
-- 
1.5.3.1

^ permalink raw reply related

* Re: [PATCH 15/40] bootwrapper: Factor out dt_set_mac_address().
From: Scott Wood @ 2007-09-24 20:12 UTC (permalink / raw)
  To: galak; +Cc: linuxppc-dev
In-Reply-To: <20070924200911.GB21347@loki.buserror.net>

Scott Wood wrote:
 > [PATCH 15/40]

Bah, that was supposed to be 1/2.  Don't worry, there's no barrage of 
patches coming. :-)

-Scott

^ permalink raw reply

* Re: Sequoia kernel crash workaround.
From: Benjamin Herrenschmidt @ 2007-09-24 20:55 UTC (permalink / raw)
  To: Valentine Barshak
  Cc: linuxppc-dev, Olof Johansson, Josh Boyer, Stefan Roese,
	David Gibson
In-Reply-To: <46F79305.9050300@ru.mvista.com>


On Mon, 2007-09-24 at 14:35 +0400, Valentine Barshak wrote:
> 
>  From what I've seen, setup_cpu is never called for BOOKE.
> Currently It's called from cputable.c for PPC64 and from head_32.S for
> 6xx.
> Thanks,

Right. We need to fix/converge some of these but it's not totally
trivial.

Ben.

^ permalink raw reply

* Re: Sequoia kernel crash workaround.
From: Josh Boyer @ 2007-09-24 21:01 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: linuxppc-dev, Olof Johansson, Josh Boyer, Stefan Roese,
	David Gibson
In-Reply-To: <1190667350.6886.59.camel@localhost.localdomain>

On Tue, 25 Sep 2007 06:55:50 +1000
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:

> 
> On Mon, 2007-09-24 at 14:35 +0400, Valentine Barshak wrote:
> > 
> >  From what I've seen, setup_cpu is never called for BOOKE.
> > Currently It's called from cputable.c for PPC64 and from head_32.S for
> > 6xx.
> > Thanks,
> 
> Right. We need to fix/converge some of these but it's not totally
> trivial.

Valentine has patches for adding this for BookE on the list.

josh

^ permalink raw reply

* Re: [patch 3/3] mpc8349emitx.dts: Add ds1339 RTC
From: Segher Boessenkool @ 2007-09-24 21:11 UTC (permalink / raw)
  To: David Gibson; +Cc: Timur Tabi, linuxppc-dev
In-Reply-To: <20070924050709.GM8058@localhost.localdomain>

>>  Scott> #size-cells is zero on i2c, so it should just be reg = <68>.
>>
>>  Scott> You'll probably need to add #address-cells and #size-cells to 
>> the
>>  Scott> controller node, as well.
>
> Uh.. yes.. i2c interfaces should really always have #a and #s.

More generally, every node that defines a bus needs it (unless the
defaults of 2 resp. 1 are correct for this bus, but even then you
might want it because it makes things more explicit).

>>  		i2c@3100 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>>  			device_type = "i2c";
>
> Hrm... we probably want an "i2c" device_type class, but I don't think
> we've actually defined one, which is a problem

By defining new device_type's, or new semantics for device_type,
you open the door to (accidentally) becoming incompatible with
"real" OF.

And you don't need to: "real" OF has a mechanism for specifying
the "generic device class" already, if you use the "generic names"
recommended practice (and you do, for both this node and the rtc
node): it's the generic name itself!

>> +			rtc@68 {
>> +				device_type = "rtc";
>> +				compatible = "dallas,ds1339";
>> +				reg = <68>;
>> +			};
>
> I think we want to think a bit more carefully about how to do bindings
> for RTC devices.  No "rtc" device_type is defined, but again we might
> want to.

Actually, "device_type" = "rtc" _is_ defined (in the "device support
extensions" recommended practice), and there is no useful way a flat
device tree can implement it (it merely defines get-time and set-time
methods).

> The fact that NVRAM+RTC chips are so common is a bit of an issue from
> the point of view of defining a device class binding - a device can't
> have type "rtc" and "nvram".

You should match OS drivers on "compatible" only anyway.

Those cases where OS drivers don't nicely 1-1 match device nodes are a
bit of a headache; for RTC/NVRAM devices, these problems are nicely
side-stepped by handling this from platform code.


Segher

^ permalink raw reply

* EBC peripheral, access causing Machine Check
From: Dave Cogley @ 2007-09-24 19:19 UTC (permalink / raw)
  To: linuxppc-embedded


[-- Attachment #1.1: Type: text/plain, Size: 916 bytes --]

Good Afternoon,

 

I am using an AMCC 440EPx processor with an FPGA peripheral attached to the
EBC.  I am doing the entire bank configuration in the u-boot boot loader
before Linux is loaded.  I can directly read and write registers using
memory read and write (md, nm) within area 0xC0000000 to 0xC000FFFF direct
memory I/O within the context of u-boot without any faults.  When I attempt
to access any register in area 0xC000000 within the context of my Linux
device driver I get a Machine Check fault (attached text) which appears to
be an access permission violation.  I am currently running the DENX ELDK
2.6.19.2 platform that was specific to the "Sequoia" platform.

 

I have configured the EBC access permissions and control resisters as
follows for bank 1:

 

PB1CR: 0xC003C000

PB1AP: 0x80040380

 

Dave Cogley

Software Engineer

Ultra Stereo Labs, Inc.

(805) 549-0161

mailto:dcogley@uslinc.com

 


[-- Attachment #1.2: Type: text/html, Size: 3940 bytes --]

[-- Attachment #2: mcdump.txt --]
[-- Type: text/plain, Size: 1767 bytes --]

bash-3.00# 

Machine check in kernel mode.
Data Read PLB Error
OPB to PLB3: BSTAT= 0x00000000
PLB3 to PLB4: BEAR=0xffffffffffffffff BESR0=0x00000000 BESR1=0x00000000
PLB4 to PLB3: BEAR=0xfffffffffffffffd BESR0=0x00000000 BESR1=0x00000000
PLB3 to OPB: BEAR=0xffffffff BESR0=0x00000000 BESR1=0x00000000
PLB3 arbiter: BEAR=0xfffffffe ACR=0x00000000 BESR=0x00000000
PLB4 to OPB1: BEAR=0x0000000dbfffffbf BESR0=0x00000000 BESR1=0x00000000
PLB40 Arbiter: BEAR=0x00000000c0000000 ACR=0xda000000 BESR0=0x0f000000
PLB41 Arbiter: BEAR=0xfffffffffffffffc ACR=0xdb000000 BESR0=0x00000000
POB0: BEAR=0xc27e3194ffffffff BESR0=0x00000000 BESR1=0x00000000
OPB0: BEAR=0x0000000000000000 BSTAT=0x00000000
Oops: machine check, sig: 7 [#2]
NIP: D107E2D4 LR: C0069F24 CTR: 0FF40B20
REGS: c02a9f50 TRAP: 0202   Not tainted  (2.6.19.2)
MSR: 00029000 <EE,ME>  CR: 40000022  XER: 00000000
TASK = cf6c1030[268] 'banjocore' THREAD: cf1b8000
GPR00: 40044B01 CF1B9EB0 CF6C1030 00000000 CF0EF5C0 40044B01 7F95B928 0FF39D08 
GPR08: 00000000 00000000 FFFFFFE7 D1080000 80000028 10018B10 00000000 100D8ED8 
GPR16: 100C0000 00000000 100C0000 10090000 00000000 100DF660 100C7C48 00000000 
GPR24: 100D9038 00000000 100D8F58 40044B01 FFFFFFF7 CF0EF5C0 0FFBB73C 7F95B928 
NIP [D107E2D4] banjo_ioctl+0xc0/0x14c [banjodecoder]
LR [C0069F24] do_ioctl+0x80/0x84
Call Trace:
[CF1B9EB0] [00000001] 0x1 (unreliable)
[CF1B9ED0] [C0069F24] do_ioctl+0x80/0x84
[CF1B9EE0] [C0069FB4] vfs_ioctl+0x8c/0x418
[CF1B9F10] [C006A380] sys_ioctl+0x40/0x74
[CF1B9F40] [C0001C84] ret_from_syscall+0x0/0x3c
Instruction dump:
60004b00 7f850000 419e0044 3c004004 60004b01 7f850000 38600000 409eff74 
3d60d108 812bf2a4 7c0004ac 7d204c2c <0c090000> 4c00012c 38600000 91260000 
Bus error
bash-3.00# 

^ permalink raw reply

* Re: [PATCH 2/3] usb: ehci-ppc-of dts bindings.
From: Segher Boessenkool @ 2007-09-24 21:40 UTC (permalink / raw)
  To: David Gibson; +Cc: linuxppc-dev, linux-usb-devel
In-Reply-To: <20070920005201.GE14404@localhost.localdomain>

>> Nothing in a flat device tree should ever define a device_type, except
>> perhaps for compatibility with legacy kernel code.
>
> This is not necessarily true.  As Segher says, device_type originally
> indicated the OF programming model for a device.  However, we've
> extended the notion for the flat device tree to allow device_type to
> cover "device classes" which could have certain common properties and
> semantics.

Such device classes are already handled by the "generic names"
recommended practice.

Reusing device_type for a different purpose is dangerous: before you
know it, you'll end up with a conflict, as was nicely demonstrated
today with device_type "rtc".

> However, in this case, a meaningful class binding must
> already be defined: it might make sense for usb to have a defined
> device_type, but it's not been defined so far, so for now you must
> omit device_type (if a device_type is defined in future, it's easier
> to add legacy hooks that will include devices which are missing the
> relevant device_type marker than to work around devices which *do*
> have the marker, but pre-date and don't follow the defined class
> binding).

Nothing in the kernel should assume it can find all devices of a
certain "class" any other way than by exhaustively matching on
possible "compatible" values.  I'm not sure why you would want to,
anyway: you need "compatible" to select which driver to use, already.


Segher

^ permalink raw reply

* Re: EBC peripheral, access causing Machine Check
From: Josh Boyer @ 2007-09-24 23:42 UTC (permalink / raw)
  To: Dave Cogley; +Cc: linuxppc-embedded
In-Reply-To: <005301c7fedf$c46f7770$9601a8c0@DCOGLEYNEW>

On Mon, 24 Sep 2007 12:19:01 -0700
"Dave Cogley" <dcogley@uslinc.com> wrote:

> Good Afternoon,
> 
>  
> 
> I am using an AMCC 440EPx processor with an FPGA peripheral attached to the
> EBC.  I am doing the entire bank configuration in the u-boot boot loader
> before Linux is loaded.  I can directly read and write registers using
> memory read and write (md, nm) within area 0xC0000000 to 0xC000FFFF direct
> memory I/O within the context of u-boot without any faults.  When I attempt
> to access any register in area 0xC000000 within the context of my Linux
> device driver I get a Machine Check fault (attached text) which appears to
> be an access permission violation.  I am currently running the DENX ELDK
> 2.6.19.2 platform that was specific to the "Sequoia" platform.
> 
>  
> 
> I have configured the EBC access permissions and control resisters as
> follows for bank 1:
> 
>  
> 
> PB1CR: 0xC003C000
> 
> PB1AP: 0x80040380

You need proper TLB entries set up before you can access things.  Linux
discards the MMU settings that U-Boot does.  So your driver needs to call 
ioremap on the physical address. 

Other than that, we can't help you much without your driver code.

josh

^ permalink raw reply

* [PATCH 1/2] powerpc: ptrace CHECK_FULL_REGS
From: Roland McGrath @ 2007-09-24 23:50 UTC (permalink / raw)
  To: Paul Mackerras, linuxppc-dev
  Cc: David Woodhouse, Andrew Morton, Linus Torvalds, linux-kernel


This restores the CHECK_FULL_REGS sanity check to every place that can
access the nonvolatile GPRs for ptrace.  This is already done for
native-bitwidth PTRACE_PEEKUSR, but was omitted for many other cases
(32-bit ptrace, PTRACE_GETREGS, etc.); I think there may have been more
uniform checks before that were lost in the recent cleanup of GETREGS et al.

Signed-off-by: Roland McGrath <roland@redhat.com>
---
 arch/powerpc/kernel/ptrace.c   |    4 ++++
 arch/powerpc/kernel/ptrace32.c |    8 ++++++++
 2 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 8a177bd..40d34b3 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -331,6 +331,7 @@ static long arch_ptrace_old(struct task_struct *child, long request, long addr,
 		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
 		unsigned long __user *tmp = (unsigned long __user *)addr;
 
+		CHECK_FULL_REGS(child->thread.regs);
 		for (i = 0; i < 32; i++) {
 			ret = put_user(*reg, tmp);
 			if (ret)
@@ -346,6 +347,7 @@ static long arch_ptrace_old(struct task_struct *child, long request, long addr,
 		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
 		unsigned long __user *tmp = (unsigned long __user *)addr;
 
+		CHECK_FULL_REGS(child->thread.regs);
 		for (i = 0; i < 32; i++) {
 			ret = get_user(*reg, tmp);
 			if (ret)
@@ -517,6 +519,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 			ret = -EIO;
 			break;
 		}
+		CHECK_FULL_REGS(child->thread.regs);
 		ret = 0;
 		for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
 			ret |= __put_user(ptrace_get_reg(child, ui),
@@ -537,6 +540,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 			ret = -EIO;
 			break;
 		}
+		CHECK_FULL_REGS(child->thread.regs);
 		ret = 0;
 		for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
 			ret = __get_user(tmp, (unsigned long __user *) data);
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c
index 9e6baea..6b86960 100644
--- a/arch/powerpc/kernel/ptrace32.c
+++ b/arch/powerpc/kernel/ptrace32.c
@@ -53,6 +53,7 @@ static long compat_ptrace_old(struct task_struct *child, long request,
 		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
 		unsigned int __user *tmp = (unsigned int __user *)addr;
 
+		CHECK_FULL_REGS(child->thread.regs);
 		for (i = 0; i < 32; i++) {
 			ret = put_user(*reg, tmp);
 			if (ret)
@@ -68,6 +69,7 @@ static long compat_ptrace_old(struct task_struct *child, long request,
 		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
 		unsigned int __user *tmp = (unsigned int __user *)addr;
 
+		CHECK_FULL_REGS(child->thread.regs);
 		for (i = 0; i < 32; i++) {
 			ret = get_user(*reg, tmp);
 			if (ret)
@@ -164,6 +166,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
 		if ((addr & 3) || (index > PT_FPSCR32))
 			break;
 
+		CHECK_FULL_REGS(child->thread.regs);
 		if (index < PT_FPR0) {
 			tmp = ptrace_get_reg(child, index);
 		} else {
@@ -210,6 +213,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
 		if ((addr & 3) || numReg > PT_FPSCR)
 			break;
 
+		CHECK_FULL_REGS(child->thread.regs);
 		if (numReg >= PT_FPR0) {
 			flush_fp_to_thread(child);
 			tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0];
@@ -270,6 +274,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
 		if ((addr & 3) || (index > PT_FPSCR32))
 			break;
 
+		CHECK_FULL_REGS(child->thread.regs);
 		if (index < PT_FPR0) {
 			ret = ptrace_put_reg(child, index, data);
 		} else {
@@ -307,6 +312,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
 		 */
 		if ((addr & 3) || (numReg > PT_FPSCR))
 			break;
+		CHECK_FULL_REGS(child->thread.regs);
 		if (numReg < PT_FPR0) {
 			unsigned long freg = ptrace_get_reg(child, numReg);
 			if (index % 2)
@@ -342,6 +348,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
 			ret = -EIO;
 			break;
 		}
+		CHECK_FULL_REGS(child->thread.regs);
 		ret = 0;
 		for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
 			ret |= __put_user(ptrace_get_reg(child, ui),
@@ -359,6 +366,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
 			ret = -EIO;
 			break;
 		}
+		CHECK_FULL_REGS(child->thread.regs);
 		ret = 0;
 		for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
 			ret = __get_user(tmp, (unsigned int __user *) data);

^ permalink raw reply related

* [PATCH 2/2] powerpc: FULL_REGS on exec
From: Roland McGrath @ 2007-09-24 23:52 UTC (permalink / raw)
  To: Paul Mackerras, linuxppc-dev
  Cc: David Woodhouse, Andrew Morton, Linus Torvalds, linux-kernel


When PTRACE_O_TRACEEXEC is used, a ptrace call to fetch the registers at
the PTRACE_EVENT_EXEC stop (PTRACE_PEEKUSR) will oops in CHECK_FULL_REGS.
With recent versions, "gdb --args /bin/sh -c 'exec /bin/true'" and "run" at
the (gdb) prompt is sufficient to produce this.  I also have written an
isolated test case, see https://bugzilla.redhat.com/show_bug.cgi?id=301791#c15.

This change fixes the problem by clearing the low bit of pt_regs.trap in
start_thread so that FULL_REGS is true again.  This is correct since all of
the GPRs that "full" refers to are cleared in start_thread.

Signed-off-by: Roland McGrath <roland@redhat.com>
---
 arch/powerpc/kernel/process.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index e477c9d..fd799d2 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -605,6 +605,13 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
 	regs->ccr = 0;
 	regs->gpr[1] = sp;
 
+	/*
+	 * We have just cleared all the nonvolatile GPRs, so make
+	 * FULL_REGS(regs) return true.  This is necessary to allow
+	 * ptrace to examine the thread immediately after exec.
+	 */
+	regs->trap &= ~1UL;
+
 #ifdef CONFIG_PPC32
 	regs->mq = 0;
 	regs->nip = start;

^ permalink raw reply related

* Re: [PATCH 1/2] powerpc: ptrace CHECK_FULL_REGS
From: Benjamin Herrenschmidt @ 2007-09-25  0:33 UTC (permalink / raw)
  To: Roland McGrath
  Cc: David Woodhouse, linux-kernel, linuxppc-dev, Paul Mackerras,
	Andrew Morton, Linus Torvalds
In-Reply-To: <20070924235052.5AFC24D04B7@magilla.localdomain>


On Mon, 2007-09-24 at 16:50 -0700, Roland McGrath wrote:
> This restores the CHECK_FULL_REGS sanity check to every place that can
> access the nonvolatile GPRs for ptrace.  This is already done for
> native-bitwidth PTRACE_PEEKUSR, but was omitted for many other cases
> (32-bit ptrace, PTRACE_GETREGS, etc.); I think there may have been more
> uniform checks before that were lost in the recent cleanup of GETREGS et al.

Yup, I think I ditched most of them.. for some reason I decided it
couldn't happen, but maybe I'm wrong ?

Cheers,
Ben.

> Signed-off-by: Roland McGrath <roland@redhat.com>
> ---
>  arch/powerpc/kernel/ptrace.c   |    4 ++++
>  arch/powerpc/kernel/ptrace32.c |    8 ++++++++
>  2 files changed, 12 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
> index 8a177bd..40d34b3 100644
> --- a/arch/powerpc/kernel/ptrace.c
> +++ b/arch/powerpc/kernel/ptrace.c
> @@ -331,6 +331,7 @@ static long arch_ptrace_old(struct task_struct *child, long request, long addr,
>  		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
>  		unsigned long __user *tmp = (unsigned long __user *)addr;
>  
> +		CHECK_FULL_REGS(child->thread.regs);
>  		for (i = 0; i < 32; i++) {
>  			ret = put_user(*reg, tmp);
>  			if (ret)
> @@ -346,6 +347,7 @@ static long arch_ptrace_old(struct task_struct *child, long request, long addr,
>  		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
>  		unsigned long __user *tmp = (unsigned long __user *)addr;
>  
> +		CHECK_FULL_REGS(child->thread.regs);
>  		for (i = 0; i < 32; i++) {
>  			ret = get_user(*reg, tmp);
>  			if (ret)
> @@ -517,6 +519,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
>  			ret = -EIO;
>  			break;
>  		}
> +		CHECK_FULL_REGS(child->thread.regs);
>  		ret = 0;
>  		for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
>  			ret |= __put_user(ptrace_get_reg(child, ui),
> @@ -537,6 +540,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
>  			ret = -EIO;
>  			break;
>  		}
> +		CHECK_FULL_REGS(child->thread.regs);
>  		ret = 0;
>  		for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
>  			ret = __get_user(tmp, (unsigned long __user *) data);
> diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c
> index 9e6baea..6b86960 100644
> --- a/arch/powerpc/kernel/ptrace32.c
> +++ b/arch/powerpc/kernel/ptrace32.c
> @@ -53,6 +53,7 @@ static long compat_ptrace_old(struct task_struct *child, long request,
>  		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
>  		unsigned int __user *tmp = (unsigned int __user *)addr;
>  
> +		CHECK_FULL_REGS(child->thread.regs);
>  		for (i = 0; i < 32; i++) {
>  			ret = put_user(*reg, tmp);
>  			if (ret)
> @@ -68,6 +69,7 @@ static long compat_ptrace_old(struct task_struct *child, long request,
>  		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
>  		unsigned int __user *tmp = (unsigned int __user *)addr;
>  
> +		CHECK_FULL_REGS(child->thread.regs);
>  		for (i = 0; i < 32; i++) {
>  			ret = get_user(*reg, tmp);
>  			if (ret)
> @@ -164,6 +166,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
>  		if ((addr & 3) || (index > PT_FPSCR32))
>  			break;
>  
> +		CHECK_FULL_REGS(child->thread.regs);
>  		if (index < PT_FPR0) {
>  			tmp = ptrace_get_reg(child, index);
>  		} else {
> @@ -210,6 +213,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
>  		if ((addr & 3) || numReg > PT_FPSCR)
>  			break;
>  
> +		CHECK_FULL_REGS(child->thread.regs);
>  		if (numReg >= PT_FPR0) {
>  			flush_fp_to_thread(child);
>  			tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0];
> @@ -270,6 +274,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
>  		if ((addr & 3) || (index > PT_FPSCR32))
>  			break;
>  
> +		CHECK_FULL_REGS(child->thread.regs);
>  		if (index < PT_FPR0) {
>  			ret = ptrace_put_reg(child, index, data);
>  		} else {
> @@ -307,6 +312,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
>  		 */
>  		if ((addr & 3) || (numReg > PT_FPSCR))
>  			break;
> +		CHECK_FULL_REGS(child->thread.regs);
>  		if (numReg < PT_FPR0) {
>  			unsigned long freg = ptrace_get_reg(child, numReg);
>  			if (index % 2)
> @@ -342,6 +348,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
>  			ret = -EIO;
>  			break;
>  		}
> +		CHECK_FULL_REGS(child->thread.regs);
>  		ret = 0;
>  		for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
>  			ret |= __put_user(ptrace_get_reg(child, ui),
> @@ -359,6 +366,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
>  			ret = -EIO;
>  			break;
>  		}
> +		CHECK_FULL_REGS(child->thread.regs);
>  		ret = 0;
>  		for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
>  			ret = __get_user(tmp, (unsigned int __user *) data);
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* Re: [PATCH 2/2] powerpc: FULL_REGS on exec
From: Benjamin Herrenschmidt @ 2007-09-25  0:34 UTC (permalink / raw)
  To: Roland McGrath
  Cc: David Woodhouse, linux-kernel, linuxppc-dev, Paul Mackerras,
	Andrew Morton, Linus Torvalds
In-Reply-To: <20070924235244.2F3BB4D04B7@magilla.localdomain>


On Mon, 2007-09-24 at 16:52 -0700, Roland McGrath wrote:
> When PTRACE_O_TRACEEXEC is used, a ptrace call to fetch the registers at
> the PTRACE_EVENT_EXEC stop (PTRACE_PEEKUSR) will oops in CHECK_FULL_REGS.
> With recent versions, "gdb --args /bin/sh -c 'exec /bin/true'" and "run" at
> the (gdb) prompt is sufficient to produce this.  I also have written an
> isolated test case, see https://bugzilla.redhat.com/show_bug.cgi?id=301791#c15.
> 
> This change fixes the problem by clearing the low bit of pt_regs.trap in
> start_thread so that FULL_REGS is true again.  This is correct since all of
> the GPRs that "full" refers to are cleared in start_thread.

Looks good, nice catch.

> Signed-off-by: Roland McGrath <roland@redhat.com>

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

> ---
>  arch/powerpc/kernel/process.c |    7 +++++++
>  1 files changed, 7 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
> index e477c9d..fd799d2 100644
> --- a/arch/powerpc/kernel/process.c
> +++ b/arch/powerpc/kernel/process.c
> @@ -605,6 +605,13 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
>  	regs->ccr = 0;
>  	regs->gpr[1] = sp;
>  
> +	/*
> +	 * We have just cleared all the nonvolatile GPRs, so make
> +	 * FULL_REGS(regs) return true.  This is necessary to allow
> +	 * ptrace to examine the thread immediately after exec.
> +	 */
> +	regs->trap &= ~1UL;
> +
>  #ifdef CONFIG_PPC32
>  	regs->mq = 0;
>  	regs->nip = start;
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* Re: [PATCH 1/2] powerpc: ptrace CHECK_FULL_REGS
From: Roland McGrath @ 2007-09-25  0:59 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: David Woodhouse, linux-kernel, linuxppc-dev, Paul Mackerras,
	Andrew Morton, Linus Torvalds
In-Reply-To: <1190680406.12382.9.camel@localhost.localdomain>

> Yup, I think I ditched most of them.. for some reason I decided it
> couldn't happen, but maybe I'm wrong ?

Well, it's a BUG_ON.  It's supposed to be for something that "can't happen".
That's why it's a sanity check, not a wild assertion. ;-)

The 2/2 patch is an example of a bug that CHECK_FULL_REGS catches.
In the status quo, using PTRACE_PEEKUSR in a bug case crashes while using
PTRACE_GETREGS in the same place might get bogus data.  (In the actual bug
thus found, the data is not bogus and only the bit that FULL_REGS checks is.)


Thanks,
Roland

^ permalink raw reply

* Re: [PATCH 15/40] bootwrapper: Factor out dt_set_mac_address().
From: David Gibson @ 2007-09-25  1:20 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <20070924200911.GB21347@loki.buserror.net>

On Mon, Sep 24, 2007 at 03:09:11PM -0500, Scott Wood wrote:
> This allows callers to set addresses one at a time when that would be more
> convenient.
> 
> Signed-off-by: Scott Wood <scottwood@freescale.com>

Sorry I've been such a pain about this previously.

Acked-by: David Gibson <david@gibson.dropbear.id.au>

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: [PATCH] Make instruction dumping work in real mode.
From: Olof Johansson @ 2007-09-25  1:41 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, paulus
In-Reply-To: <20070924190100.GB4761@loki.buserror.net>

On Mon, Sep 24, 2007 at 02:01:00PM -0500, Scott Wood wrote:
> On non-book-E, if a faulting PC is in the first few pages, and it's not an
> ITLB miss, it's likely executing in real mode, probably at an exception vector.
> 
> Rather than print a useless XXXXXXXX, it is assumed that this is the case, and
> the address is treated as physical.  This helps when debugging corruption at
> the beginning of memory.

Please use regs->msr & MSR_IR instead.


-Olof

^ permalink raw reply

* Re: [PATCH 2/2] bootwrapper: Add PlanetCore firmware support.
From: David Gibson @ 2007-09-25  1:52 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <20070924200949.GC21347@loki.buserror.net>

On Mon, Sep 24, 2007 at 03:09:49PM -0500, Scott Wood wrote:
> This is a library that board code can use to extract information from the
> PlanetCore configuration keys.  PlanetCore is used on various boards from
> Embedded Planet.
> 
> Signed-off-by: Scott Wood <scottwood@freescale.com>
Acked-by: David Gibson <david@gibson.dropbear.id.au>

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: [PATCH v2] bootwrapper: adds cuboot for MPC7448HPC2 platform
From: David Gibson @ 2007-09-25  1:57 UTC (permalink / raw)
  To: Zang Roy-r61911; +Cc: linuxppc-dev list, Paul Mackerras
In-Reply-To: <1190629915.20267.8.camel@localhost.localdomain>

On Mon, Sep 24, 2007 at 06:31:55PM +0800, Zang Roy-r61911 wrote:
> From: Roy Zang <tie-fei.zang@freescale.com>
> 
> This patch adds cuboot support for MPC7448HPC2 platform.
> The cuImage can be used with legacy u-boot without FDT support.
> 
> Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
Acked-by: David Gibson <david@gibson.dropbear.id.au>

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: [patch 3/3] mpc8349emitx.dts: Add ds1339 RTC
From: David Gibson @ 2007-09-25  2:04 UTC (permalink / raw)
  To: Scott Wood; +Cc: Timur Tabi, linuxppc-dev
In-Reply-To: <46F7CF2F.9070805@freescale.com>

On Mon, Sep 24, 2007 at 09:52:31AM -0500, Scott Wood wrote:
> David Gibson wrote:
> >>  		i2c@3100 {
> >> +			#address-cells = <1>;
> >> +			#size-cells = <0>;
> >>  			device_type = "i2c";
> > 
> > Hrm... we probably want an "i2c" device_type class, but I don't think
> > we've actually defined one, which is a problem
> 
> Right... but we need to get the kernel to stop expecting the device type 
> to be there before we yell at people for including it. :-)

Obviously.  We should make sure all the corresponding compatibles are
specific enough, change the drivers, then think about getting rid of
it.

> > The fact that NVRAM+RTC chips are so common is a bit of an issue from
> > the point of view of defining a device class binding - a device can't
> > have type "rtc" and "nvram".
> 
> This is one of the reasons that I'd prefer to use compatible for such 
> things.

Yeah, fair enough.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: AMCC yosemite 440ep PCI slot doesn't work.
From: Andrew Liu @ 2007-09-25  2:02 UTC (permalink / raw)
  To: Stefan Roese; +Cc: linuxppc-dev
In-Reply-To: <200709241314.18123.sr@denx.de>

I have tested it on linux-2.6.19 which is from AMCC website ,  linux 
2.6.21.7 which is from linux mainline and  linux-2.6.23.rc7 which is
from git://www.denx.de/git/linux-2.6-denx.git
Have the same problem.
 I don't understand, why after enabling this PCI interrupts.  in so
short time, produce 100,000 interrupt request (25:     100000  UIC0
Level     eth2).


BRs,
Andrew.

Stefan Roese wrote:
> On Monday 24 September 2007, Andrew Liu wrote:
>   
>> By default, it is IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE
>>     
>
> And that should be correct for PCI interrupts.
>
>   
>>  I change it to IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE  or
>> IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE.
>> It  displays:
>> eth2: link up, 100Mbps, full-duplex, lpa 0x45E1
>> eth2: no IPv6 routers present
>> NETDEV WATCHDOG: eth2: transmit timed out
>> eth2: Transmit timeout, status 0c 0005 c07f media 10.
>> eth2: Tx queue start entry 4  dirty entry 0.
>> eth2:  Tx descriptor 0 is 0008a05a. (queue head)
>> eth2:  Tx descriptor 1 is 0008a04e.
>> eth2:  Tx descriptor 2 is 0008a046.
>> eth2:  Tx descriptor 3 is 0008a05a.
>> eth2: link up, 100Mbps, full-duplex, lpa 0x45E1
>>
>> and
>> root@localhost:/root> ifconfig  eth2
>> eth2      Link encap:Ethernet  HWaddr 00:0E:2E:7E:F5:E6
>>           inet addr:128.224.149.13  Bcast:128.224.255.255  Mask:255.255.0.0
>>           inet6 addr: fe80::20e:2eff:fe7e:f5e6/64 Scope:Link
>>           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
>>           RX packets:0 errors:0 dropped:0 overruns:0 frame:0
>>           TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
>>           collisions:0 txqueuelen:1000
>>           RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)
>>           Interrupt:25 Base address:0x6f00
>>
>>
>> and
>> root@localhost:/root> cat /proc/interrupts
>>            CPU0
>>   2:          0  UIC0 Edge      IBM IIC
>>   7:          0  UIC0 Edge      IBM IIC
>>  10:      11961  UIC0 Edge      MAL TX EOB
>>  11:      18471  UIC0 Edge      MAL RX EOB
>>  25:          0  UIC0 Edge      eth2
>>  32:          0  UIC1 Edge      MAL SERR
>>  33:          0  UIC1 Edge      MAL TX DE
>>  34:          0  UIC1 Edge      MAL RX DE
>>  40:         32  UIC1 Edge      ohci_hcd:usb1
>>  60:          0  UIC1 Edge      EMAC
>> BAD:          0
>>
>>
>> Can PCI slot use level trigger?
>>
>> give me some advice.
>>     
>
> Hmmm. Did you try an earlier Linux version too? For example 2.6.22 or even 
> earlier? Please give it a try and let us know if the same problem occurs.
>
> Best regards,
> Stefan
>
> =====================================================================
> DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de
> =====================================================================
>
>   

^ permalink raw reply

* Re: AMCC yosemite 440ep PCI slot doesn't work.
From: Andrew Liu @ 2007-09-25  2:05 UTC (permalink / raw)
  To: Valentine Barshak; +Cc: linuxppc-dev, Stefan Roese
In-Reply-To: <46F79D6C.5070500@ru.mvista.com>

Currently, ppc44x use ppc branch, not powerpc, especially for AMCC
yosemite 440ep.

Through adding printk in function ppc4xx_pic_init which is in
arch/ppc/syslib/ppc4xx_pic.c, whether setting  IRQ_LEVEL has no effect
on it.



BRs,
Andrew


Valentine Barshak wrote:
> Stefan Roese wrote:
>> On Monday 24 September 2007, Andrew Liu wrote:
>>> By default, it is IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE
>>
>> And that should be correct for PCI interrupts.
>>
>>>  I change it to IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE  or
>>> IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE.
>>> It  displays:
>>> eth2: link up, 100Mbps, full-duplex, lpa 0x45E1
>>> eth2: no IPv6 routers present
>>> NETDEV WATCHDOG: eth2: transmit timed out
>>> eth2: Transmit timeout, status 0c 0005 c07f media 10.
>>> eth2: Tx queue start entry 4  dirty entry 0.
>>> eth2:  Tx descriptor 0 is 0008a05a. (queue head)
>>> eth2:  Tx descriptor 1 is 0008a04e.
>>> eth2:  Tx descriptor 2 is 0008a046.
>>> eth2:  Tx descriptor 3 is 0008a05a.
>>> eth2: link up, 100Mbps, full-duplex, lpa 0x45E1
>>>
>>> and
>>> root@localhost:/root> ifconfig  eth2
>>> eth2      Link encap:Ethernet  HWaddr 00:0E:2E:7E:F5:E6
>>>           inet addr:128.224.149.13  Bcast:128.224.255.255 
>>> Mask:255.255.0.0
>>>           inet6 addr: fe80::20e:2eff:fe7e:f5e6/64 Scope:Link
>>>           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
>>>           RX packets:0 errors:0 dropped:0 overruns:0 frame:0
>>>           TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
>>>           collisions:0 txqueuelen:1000
>>>           RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)
>>>           Interrupt:25 Base address:0x6f00
>>>
>>>
>>> and
>>> root@localhost:/root> cat /proc/interrupts
>>>            CPU0
>>>   2:          0  UIC0 Edge      IBM IIC
>>>   7:          0  UIC0 Edge      IBM IIC
>>>  10:      11961  UIC0 Edge      MAL TX EOB
>>>  11:      18471  UIC0 Edge      MAL RX EOB
>>>  25:          0  UIC0 Edge      eth2
>>>  32:          0  UIC1 Edge      MAL SERR
>>>  33:          0  UIC1 Edge      MAL TX DE
>>>  34:          0  UIC1 Edge      MAL RX DE
>>>  40:         32  UIC1 Edge      ohci_hcd:usb1
>>>  60:          0  UIC1 Edge      EMAC
>>> BAD:          0
>>>
>>>
>>> Can PCI slot use level trigger?
>>>
>>> give me some advice.
>
> This could be caused by misseting the IRQ_lEVEL flag in desc->status.
> There have been a commit 4dc7b4b0405fd7320940849b6e31ea8ea68fd0df that
> fixes the problem.
> Thanks,
> Valentine.
>
>>
>> Hmmm. Did you try an earlier Linux version too? For example 2.6.22 or
>> even earlier? Please give it a try and let us know if the same
>> problem occurs.
>>
>> Best regards,
>> Stefan
>>
>> =====================================================================
>> DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
>> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
>> Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de
>> =====================================================================
>
>

^ permalink raw reply

* Re: [patch 3/3] mpc8349emitx.dts: Add ds1339 RTC
From: David Gibson @ 2007-09-25  2:11 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linuxppc-dev, Timur Tabi
In-Reply-To: <b312e03ef67dcd6cdc5f57e90da746ef@kernel.crashing.org>

On Mon, Sep 24, 2007 at 11:11:28PM +0200, Segher Boessenkool wrote:
> >>  Scott> #size-cells is zero on i2c, so it should just be reg = <68>.
> >>
> >>  Scott> You'll probably need to add #address-cells and #size-cells to 
> >> the
> >>  Scott> controller node, as well.
> >
> > Uh.. yes.. i2c interfaces should really always have #a and #s.
> 
> More generally, every node that defines a bus needs it (unless the
> defaults of 2 resp. 1 are correct for this bus, but even then you
> might want it because it makes things more explicit).

Yes.  Actually I think we should make explicit #a and #s at least
strongly recommended in the flat tree documentation.

> >>  		i2c@3100 {
> >> +			#address-cells = <1>;
> >> +			#size-cells = <0>;
> >>  			device_type = "i2c";
> >
> > Hrm... we probably want an "i2c" device_type class, but I don't think
> > we've actually defined one, which is a problem
> 
> By defining new device_type's, or new semantics for device_type,
> you open the door to (accidentally) becoming incompatible with
> "real" OF.

Hrm... perhaps.  But is it a realistic danger - I'll have to think
more about that.

> And you don't need to: "real" OF has a mechanism for specifying
> the "generic device class" already, if you use the "generic names"
> recommended practice (and you do, for both this node and the rtc
> node): it's the generic name itself!

Hmm, I guess.

> >> +			rtc@68 {
> >> +				device_type = "rtc";
> >> +				compatible = "dallas,ds1339";
> >> +				reg = <68>;
> >> +			};
> >
> > I think we want to think a bit more carefully about how to do bindings
> > for RTC devices.  No "rtc" device_type is defined, but again we might
> > want to.
> 
> Actually, "device_type" = "rtc" _is_ defined (in the "device support
> extensions" recommended practice), and there is no useful way a flat
> device tree can implement it (it merely defines get-time and set-time
> methods).

Ah.. right.  That changes things a bit, in that we might want to
include device_type purely for similarity with real OF tree.

Real OF has a device_type == "nvram" too, doesn't it?  AFAICT the real
OF systems I have (which I think all have ISA-like CMOS RTC/NVRAM
chips) the RTC is labelled as "nvram" rather than "rtc".

> > The fact that NVRAM+RTC chips are so common is a bit of an issue from
> > the point of view of defining a device class binding - a device can't
> > have type "rtc" and "nvram".
> 
> You should match OS drivers on "compatible" only anyway.

Absolutely.  I was only thinking of defining "device classes" where
for some reason it is useful to examine them without needing to pick a
particular driver.

> Those cases where OS drivers don't nicely 1-1 match device nodes are a
> bit of a headache; for RTC/NVRAM devices, these problems are nicely
> side-stepped by handling this from platform code.

Not necessarily.  The new RTC class drivers are just drivers like
anything other and are not especially instantiated from the platform
code.


And drat.  I was only really mentioning stuff about device_type in
passing, but it's the only thing anyone's responded to.  I was also
mostly suggesting changing the format of compatible, for greater
similarity with the existing ds1385 binding.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox