LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V15 3/4] ptp: Added a clock driver for the IXP46x.
From: Richard Cochran @ 2011-04-22 10:04 UTC (permalink / raw)
  To: linux-kernel
  Cc: Thomas Gleixner, Rodolfo Giometti, Arnd Bergmann, Peter Zijlstra,
	linux-api, devicetree-discuss, Russell King, Paul Mackerras,
	John Stultz, linux-arm-kernel, netdev, Ben Hutchings,
	Mike Frysinger, Christoph Lameter, linuxppc-dev, David Miller,
	Alan Cox, Krzysztof Halasa
In-Reply-To: <cover.1303466102.git.richard.cochran@omicron.at>

This patch adds a driver for the hardware time stamping unit found on the
IXP465. The basic clock operations and an external trigger are implemented.

Signed-off-by: Richard Cochran <richard.cochran@omicron.at>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: David S. Miller <davem@davemloft.net>
Acked-by: John Stultz <john.stultz@linaro.org>
Acked-by: Krzysztof Halasa <khc@pm.waw.pl>
---
 arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h |   78 ++++++
 drivers/net/arm/ixp4xx_eth.c                  |  195 ++++++++++++++-
 drivers/ptp/Kconfig                           |   13 +
 drivers/ptp/Makefile                          |    1 +
 drivers/ptp/ptp_ixp46x.c                      |  332 +++++++++++++++++++++++++
 5 files changed, 616 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h
 create mode 100644 drivers/ptp/ptp_ixp46x.c

diff --git a/arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h b/arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h
new file mode 100644
index 0000000..292d55e
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h
@@ -0,0 +1,78 @@
+/*
+ * PTP 1588 clock using the IXP46X
+ *
+ * Copyright (C) 2010 OMICRON electronics GmbH
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _IXP46X_TS_H_
+#define _IXP46X_TS_H_
+
+#define DEFAULT_ADDEND 0xF0000029
+#define TICKS_NS_SHIFT 4
+
+struct ixp46x_channel_ctl {
+	u32 ch_control;  /* 0x40 Time Synchronization Channel Control */
+	u32 ch_event;    /* 0x44 Time Synchronization Channel Event */
+	u32 tx_snap_lo;  /* 0x48 Transmit Snapshot Low Register */
+	u32 tx_snap_hi;  /* 0x4C Transmit Snapshot High Register */
+	u32 rx_snap_lo;  /* 0x50 Receive Snapshot Low Register */
+	u32 rx_snap_hi;  /* 0x54 Receive Snapshot High Register */
+	u32 src_uuid_lo; /* 0x58 Source UUID0 Low Register */
+	u32 src_uuid_hi; /* 0x5C Sequence Identifier/Source UUID0 High */
+};
+
+struct ixp46x_ts_regs {
+	u32 control;     /* 0x00 Time Sync Control Register */
+	u32 event;       /* 0x04 Time Sync Event Register */
+	u32 addend;      /* 0x08 Time Sync Addend Register */
+	u32 accum;       /* 0x0C Time Sync Accumulator Register */
+	u32 test;        /* 0x10 Time Sync Test Register */
+	u32 unused;      /* 0x14 */
+	u32 rsystime_lo; /* 0x18 RawSystemTime_Low Register */
+	u32 rsystime_hi; /* 0x1C RawSystemTime_High Register */
+	u32 systime_lo;  /* 0x20 SystemTime_Low Register */
+	u32 systime_hi;  /* 0x24 SystemTime_High Register */
+	u32 trgt_lo;     /* 0x28 TargetTime_Low Register */
+	u32 trgt_hi;     /* 0x2C TargetTime_High Register */
+	u32 asms_lo;     /* 0x30 Auxiliary Slave Mode Snapshot Low  */
+	u32 asms_hi;     /* 0x34 Auxiliary Slave Mode Snapshot High */
+	u32 amms_lo;     /* 0x38 Auxiliary Master Mode Snapshot Low */
+	u32 amms_hi;     /* 0x3C Auxiliary Master Mode Snapshot High */
+
+	struct ixp46x_channel_ctl channel[3];
+};
+
+/* 0x00 Time Sync Control Register Bits */
+#define TSCR_AMM (1<<3)
+#define TSCR_ASM (1<<2)
+#define TSCR_TTM (1<<1)
+#define TSCR_RST (1<<0)
+
+/* 0x04 Time Sync Event Register Bits */
+#define TSER_SNM (1<<3)
+#define TSER_SNS (1<<2)
+#define TTIPEND  (1<<1)
+
+/* 0x40 Time Synchronization Channel Control Register Bits */
+#define MASTER_MODE   (1<<0)
+#define TIMESTAMP_ALL (1<<1)
+
+/* 0x44 Time Synchronization Channel Event Register Bits */
+#define TX_SNAPSHOT_LOCKED (1<<0)
+#define RX_SNAPSHOT_LOCKED (1<<1)
+
+#endif
diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c
index 9eb9b98..de51e84 100644
--- a/drivers/net/arm/ixp4xx_eth.c
+++ b/drivers/net/arm/ixp4xx_eth.c
@@ -30,9 +30,12 @@
 #include <linux/etherdevice.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
+#include <linux/net_tstamp.h>
 #include <linux/phy.h>
 #include <linux/platform_device.h>
+#include <linux/ptp_classify.h>
 #include <linux/slab.h>
+#include <mach/ixp46x_ts.h>
 #include <mach/npe.h>
 #include <mach/qmgr.h>
 
@@ -67,6 +70,10 @@
 #define RXFREE_QUEUE(port_id)	(NPE_ID(port_id) + 26)
 #define TXDONE_QUEUE		31
 
+#define PTP_SLAVE_MODE		1
+#define PTP_MASTER_MODE		2
+#define PORT2CHANNEL(p)		NPE_ID(p->id)
+
 /* TX Control Registers */
 #define TX_CNTRL0_TX_EN		0x01
 #define TX_CNTRL0_HALFDUPLEX	0x02
@@ -171,6 +178,8 @@ struct port {
 	int id;			/* logical port ID */
 	int speed, duplex;
 	u8 firmware[4];
+	int hwts_tx_en;
+	int hwts_rx_en;
 };
 
 /* NPE message structure */
@@ -246,6 +255,172 @@ static int ports_open;
 static struct port *npe_port_tab[MAX_NPES];
 static struct dma_pool *dma_pool;
 
+static struct sock_filter ptp_filter[] = {
+	PTP_FILTER
+};
+
+static int ixp_ptp_match(struct sk_buff *skb, u16 uid_hi, u32 uid_lo, u16 seqid)
+{
+	u8 *data = skb->data;
+	unsigned int offset;
+	u16 *hi, *id;
+	u32 lo;
+
+	if (sk_run_filter(skb, ptp_filter) != PTP_CLASS_V1_IPV4)
+		return 0;
+
+	offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
+
+	if (skb->len < offset + OFF_PTP_SEQUENCE_ID + sizeof(seqid))
+		return 0;
+
+	hi = (u16 *)(data + offset + OFF_PTP_SOURCE_UUID);
+	id = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
+
+	memcpy(&lo, &hi[1], sizeof(lo));
+
+	return (uid_hi == ntohs(*hi) &&
+		uid_lo == ntohl(lo) &&
+		seqid  == ntohs(*id));
+}
+
+static void ixp_rx_timestamp(struct port *port, struct sk_buff *skb)
+{
+	struct skb_shared_hwtstamps *shhwtstamps;
+	struct ixp46x_ts_regs *regs;
+	u64 ns;
+	u32 ch, hi, lo, val;
+	u16 uid, seq;
+
+	if (!port->hwts_rx_en)
+		return;
+
+	ch = PORT2CHANNEL(port);
+
+	regs = (struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT;
+
+	val = __raw_readl(&regs->channel[ch].ch_event);
+
+	if (!(val & RX_SNAPSHOT_LOCKED))
+		return;
+
+	lo = __raw_readl(&regs->channel[ch].src_uuid_lo);
+	hi = __raw_readl(&regs->channel[ch].src_uuid_hi);
+
+	uid = hi & 0xffff;
+	seq = (hi >> 16) & 0xffff;
+
+	if (!ixp_ptp_match(skb, htons(uid), htonl(lo), htons(seq)))
+		goto out;
+
+	lo = __raw_readl(&regs->channel[ch].rx_snap_lo);
+	hi = __raw_readl(&regs->channel[ch].rx_snap_hi);
+	ns = ((u64) hi) << 32;
+	ns |= lo;
+	ns <<= TICKS_NS_SHIFT;
+
+	shhwtstamps = skb_hwtstamps(skb);
+	memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+	shhwtstamps->hwtstamp = ns_to_ktime(ns);
+out:
+	__raw_writel(RX_SNAPSHOT_LOCKED, &regs->channel[ch].ch_event);
+}
+
+static void ixp_tx_timestamp(struct port *port, struct sk_buff *skb)
+{
+	struct skb_shared_hwtstamps shhwtstamps;
+	struct ixp46x_ts_regs *regs;
+	struct skb_shared_info *shtx;
+	u64 ns;
+	u32 ch, cnt, hi, lo, val;
+
+	shtx = skb_shinfo(skb);
+	if (unlikely(shtx->tx_flags & SKBTX_HW_TSTAMP && port->hwts_tx_en))
+		shtx->tx_flags |= SKBTX_IN_PROGRESS;
+	else
+		return;
+
+	ch = PORT2CHANNEL(port);
+
+	regs = (struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT;
+
+	/*
+	 * This really stinks, but we have to poll for the Tx time stamp.
+	 * Usually, the time stamp is ready after 4 to 6 microseconds.
+	 */
+	for (cnt = 0; cnt < 100; cnt++) {
+		val = __raw_readl(&regs->channel[ch].ch_event);
+		if (val & TX_SNAPSHOT_LOCKED)
+			break;
+		udelay(1);
+	}
+	if (!(val & TX_SNAPSHOT_LOCKED)) {
+		shtx->tx_flags &= ~SKBTX_IN_PROGRESS;
+		return;
+	}
+
+	lo = __raw_readl(&regs->channel[ch].tx_snap_lo);
+	hi = __raw_readl(&regs->channel[ch].tx_snap_hi);
+	ns = ((u64) hi) << 32;
+	ns |= lo;
+	ns <<= TICKS_NS_SHIFT;
+
+	memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+	shhwtstamps.hwtstamp = ns_to_ktime(ns);
+	skb_tstamp_tx(skb, &shhwtstamps);
+
+	__raw_writel(TX_SNAPSHOT_LOCKED, &regs->channel[ch].ch_event);
+}
+
+static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	struct hwtstamp_config cfg;
+	struct ixp46x_ts_regs *regs;
+	struct port *port = netdev_priv(netdev);
+	int ch;
+
+	if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
+		return -EFAULT;
+
+	if (cfg.flags) /* reserved for future extensions */
+		return -EINVAL;
+
+	ch = PORT2CHANNEL(port);
+	regs = (struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT;
+
+	switch (cfg.tx_type) {
+	case HWTSTAMP_TX_OFF:
+		port->hwts_tx_en = 0;
+		break;
+	case HWTSTAMP_TX_ON:
+		port->hwts_tx_en = 1;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	switch (cfg.rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		port->hwts_rx_en = 0;
+		break;
+	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+		port->hwts_rx_en = PTP_SLAVE_MODE;
+		__raw_writel(0, &regs->channel[ch].ch_control);
+		break;
+	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+		port->hwts_rx_en = PTP_MASTER_MODE;
+		__raw_writel(MASTER_MODE, &regs->channel[ch].ch_control);
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	/* Clear out any old time stamps. */
+	__raw_writel(TX_SNAPSHOT_LOCKED | RX_SNAPSHOT_LOCKED,
+		     &regs->channel[ch].ch_event);
+
+	return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
+}
 
 static int ixp4xx_mdio_cmd(struct mii_bus *bus, int phy_id, int location,
 			   int write, u16 cmd)
@@ -573,6 +748,7 @@ static int eth_poll(struct napi_struct *napi, int budget)
 
 		debug_pkt(dev, "eth_poll", skb->data, skb->len);
 
+		ixp_rx_timestamp(port, skb);
 		skb->protocol = eth_type_trans(skb, dev);
 		dev->stats.rx_packets++;
 		dev->stats.rx_bytes += skb->len;
@@ -679,14 +855,12 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev)
 		return NETDEV_TX_OK;
 	}
 	memcpy_swab32(mem, (u32 *)((int)skb->data & ~3), bytes / 4);
-	dev_kfree_skb(skb);
 #endif
 
 	phys = dma_map_single(&dev->dev, mem, bytes, DMA_TO_DEVICE);
 	if (dma_mapping_error(&dev->dev, phys)) {
-#ifdef __ARMEB__
 		dev_kfree_skb(skb);
-#else
+#ifndef __ARMEB__
 		kfree(mem);
 #endif
 		dev->stats.tx_dropped++;
@@ -728,6 +902,13 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev)
 #if DEBUG_TX
 	printk(KERN_DEBUG "%s: eth_xmit end\n", dev->name);
 #endif
+
+	ixp_tx_timestamp(port, skb);
+	skb_tx_timestamp(skb);
+
+#ifndef __ARMEB__
+	dev_kfree_skb(skb);
+#endif
 	return NETDEV_TX_OK;
 }
 
@@ -783,6 +964,9 @@ static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
 	if (!netif_running(dev))
 		return -EINVAL;
 
+	if (cpu_is_ixp46x() && cmd == SIOCSHWTSTAMP)
+		return hwtstamp_ioctl(dev, req, cmd);
+
 	return phy_mii_ioctl(port->phydev, req, cmd);
 }
 
@@ -1171,6 +1355,11 @@ static int __devinit eth_init_one(struct platform_device *pdev)
 	char phy_id[MII_BUS_ID_SIZE + 3];
 	int err;
 
+	if (ptp_filter_init(ptp_filter, ARRAY_SIZE(ptp_filter))) {
+		pr_err("ixp4xx_eth: bad ptp filter\n");
+		return -EINVAL;
+	}
+
 	if (!(dev = alloc_etherdev(sizeof(struct port))))
 		return -ENOMEM;
 
diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index 12eb844..fcfafd0 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -40,4 +40,17 @@ config PTP_1588_CLOCK_GIANFAR
 	  To compile this driver as a module, choose M here: the module
 	  will be called gianfar_ptp.
 
+config PTP_1588_CLOCK_IXP46X
+	tristate "Intel IXP46x as PTP clock"
+	depends on PTP_1588_CLOCK
+	depends on IXP4XX_ETH
+	help
+	  This driver adds support for using the IXP46X as a PTP
+	  clock. This clock is only useful if your PTP programs are
+	  getting hardware time stamps on the PTP Ethernet packets
+	  using the SO_TIMESTAMPING API.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called ptp_ixp46x.
+
 endmenu
diff --git a/drivers/ptp/Makefile b/drivers/ptp/Makefile
index 480e2af..f6933e8 100644
--- a/drivers/ptp/Makefile
+++ b/drivers/ptp/Makefile
@@ -4,3 +4,4 @@
 
 ptp-y					:= ptp_clock.o ptp_chardev.o ptp_sysfs.o
 obj-$(CONFIG_PTP_1588_CLOCK)		+= ptp.o
+obj-$(CONFIG_PTP_1588_CLOCK_IXP46X)	+= ptp_ixp46x.o
diff --git a/drivers/ptp/ptp_ixp46x.c b/drivers/ptp/ptp_ixp46x.c
new file mode 100644
index 0000000..803d665
--- /dev/null
+++ b/drivers/ptp/ptp_ixp46x.c
@@ -0,0 +1,332 @@
+/*
+ * PTP 1588 clock using the IXP46X
+ *
+ * Copyright (C) 2010 OMICRON electronics GmbH
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <linux/ptp_clock_kernel.h>
+#include <mach/ixp46x_ts.h>
+
+#define DRIVER		"ptp_ixp46x"
+#define N_EXT_TS	2
+#define MASTER_GPIO	8
+#define MASTER_IRQ	25
+#define SLAVE_GPIO	7
+#define SLAVE_IRQ	24
+
+struct ixp_clock {
+	struct ixp46x_ts_regs *regs;
+	struct ptp_clock *ptp_clock;
+	struct ptp_clock_info caps;
+	int exts0_enabled;
+	int exts1_enabled;
+};
+
+DEFINE_SPINLOCK(register_lock);
+
+/*
+ * Register access functions
+ */
+
+static u64 ixp_systime_read(struct ixp46x_ts_regs *regs)
+{
+	u64 ns;
+	u32 lo, hi;
+
+	lo = __raw_readl(&regs->systime_lo);
+	hi = __raw_readl(&regs->systime_hi);
+
+	ns = ((u64) hi) << 32;
+	ns |= lo;
+	ns <<= TICKS_NS_SHIFT;
+
+	return ns;
+}
+
+static void ixp_systime_write(struct ixp46x_ts_regs *regs, u64 ns)
+{
+	u32 hi, lo;
+
+	ns >>= TICKS_NS_SHIFT;
+	hi = ns >> 32;
+	lo = ns & 0xffffffff;
+
+	__raw_writel(lo, &regs->systime_lo);
+	__raw_writel(hi, &regs->systime_hi);
+}
+
+/*
+ * Interrupt service routine
+ */
+
+static irqreturn_t isr(int irq, void *priv)
+{
+	struct ixp_clock *ixp_clock = priv;
+	struct ixp46x_ts_regs *regs = ixp_clock->regs;
+	struct ptp_clock_event event;
+	u32 ack = 0, lo, hi, val;
+
+	val = __raw_readl(&regs->event);
+
+	if (val & TSER_SNS) {
+		ack |= TSER_SNS;
+		if (ixp_clock->exts0_enabled) {
+			hi = __raw_readl(&regs->asms_hi);
+			lo = __raw_readl(&regs->asms_lo);
+			event.type = PTP_CLOCK_EXTTS;
+			event.index = 0;
+			event.timestamp = ((u64) hi) << 32;
+			event.timestamp |= lo;
+			event.timestamp <<= TICKS_NS_SHIFT;
+			ptp_clock_event(ixp_clock->ptp_clock, &event);
+		}
+	}
+
+	if (val & TSER_SNM) {
+		ack |= TSER_SNM;
+		if (ixp_clock->exts1_enabled) {
+			hi = __raw_readl(&regs->amms_hi);
+			lo = __raw_readl(&regs->amms_lo);
+			event.type = PTP_CLOCK_EXTTS;
+			event.index = 1;
+			event.timestamp = ((u64) hi) << 32;
+			event.timestamp |= lo;
+			event.timestamp <<= TICKS_NS_SHIFT;
+			ptp_clock_event(ixp_clock->ptp_clock, &event);
+		}
+	}
+
+	if (val & TTIPEND)
+		ack |= TTIPEND; /* this bit seems to be always set */
+
+	if (ack) {
+		__raw_writel(ack, &regs->event);
+		return IRQ_HANDLED;
+	} else
+		return IRQ_NONE;
+}
+
+/*
+ * PTP clock operations
+ */
+
+static int ptp_ixp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+	u64 adj;
+	u32 diff, addend;
+	int neg_adj = 0;
+	struct ixp_clock *ixp_clock = container_of(ptp, struct ixp_clock, caps);
+	struct ixp46x_ts_regs *regs = ixp_clock->regs;
+
+	if (ppb < 0) {
+		neg_adj = 1;
+		ppb = -ppb;
+	}
+	addend = DEFAULT_ADDEND;
+	adj = addend;
+	adj *= ppb;
+	diff = div_u64(adj, 1000000000ULL);
+
+	addend = neg_adj ? addend - diff : addend + diff;
+
+	__raw_writel(addend, &regs->addend);
+
+	return 0;
+}
+
+static int ptp_ixp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+	s64 now;
+	unsigned long flags;
+	struct ixp_clock *ixp_clock = container_of(ptp, struct ixp_clock, caps);
+	struct ixp46x_ts_regs *regs = ixp_clock->regs;
+
+	spin_lock_irqsave(&register_lock, flags);
+
+	now = ixp_systime_read(regs);
+	now += delta;
+	ixp_systime_write(regs, now);
+
+	spin_unlock_irqrestore(&register_lock, flags);
+
+	return 0;
+}
+
+static int ptp_ixp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+	u64 ns;
+	u32 remainder;
+	unsigned long flags;
+	struct ixp_clock *ixp_clock = container_of(ptp, struct ixp_clock, caps);
+	struct ixp46x_ts_regs *regs = ixp_clock->regs;
+
+	spin_lock_irqsave(&register_lock, flags);
+
+	ns = ixp_systime_read(regs);
+
+	spin_unlock_irqrestore(&register_lock, flags);
+
+	ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder);
+	ts->tv_nsec = remainder;
+	return 0;
+}
+
+static int ptp_ixp_settime(struct ptp_clock_info *ptp,
+			   const struct timespec *ts)
+{
+	u64 ns;
+	unsigned long flags;
+	struct ixp_clock *ixp_clock = container_of(ptp, struct ixp_clock, caps);
+	struct ixp46x_ts_regs *regs = ixp_clock->regs;
+
+	ns = ts->tv_sec * 1000000000ULL;
+	ns += ts->tv_nsec;
+
+	spin_lock_irqsave(&register_lock, flags);
+
+	ixp_systime_write(regs, ns);
+
+	spin_unlock_irqrestore(&register_lock, flags);
+
+	return 0;
+}
+
+static int ptp_ixp_enable(struct ptp_clock_info *ptp,
+			  struct ptp_clock_request *rq, int on)
+{
+	struct ixp_clock *ixp_clock = container_of(ptp, struct ixp_clock, caps);
+
+	switch (rq->type) {
+	case PTP_CLK_REQ_EXTTS:
+		switch (rq->extts.index) {
+		case 0:
+			ixp_clock->exts0_enabled = on ? 1 : 0;
+			break;
+		case 1:
+			ixp_clock->exts1_enabled = on ? 1 : 0;
+			break;
+		default:
+			return -EINVAL;
+		}
+		return 0;
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static struct ptp_clock_info ptp_ixp_caps = {
+	.owner		= THIS_MODULE,
+	.name		= "IXP46X timer",
+	.max_adj	= 66666655,
+	.n_ext_ts	= N_EXT_TS,
+	.pps		= 0,
+	.adjfreq	= ptp_ixp_adjfreq,
+	.adjtime	= ptp_ixp_adjtime,
+	.gettime	= ptp_ixp_gettime,
+	.settime	= ptp_ixp_settime,
+	.enable		= ptp_ixp_enable,
+};
+
+/* module operations */
+
+static struct ixp_clock ixp_clock;
+
+static int setup_interrupt(int gpio)
+{
+	int irq;
+
+	gpio_line_config(gpio, IXP4XX_GPIO_IN);
+
+	irq = gpio_to_irq(gpio);
+
+	if (NO_IRQ == irq)
+		return NO_IRQ;
+
+	if (irq_set_irq_type(irq, IRQF_TRIGGER_FALLING)) {
+		pr_err("cannot set trigger type for irq %d\n", irq);
+		return NO_IRQ;
+	}
+
+	if (request_irq(irq, isr, 0, DRIVER, &ixp_clock)) {
+		pr_err("request_irq failed for irq %d\n", irq);
+		return NO_IRQ;
+	}
+
+	return irq;
+}
+
+static void __exit ptp_ixp_exit(void)
+{
+	free_irq(MASTER_IRQ, &ixp_clock);
+	free_irq(SLAVE_IRQ, &ixp_clock);
+	ptp_clock_unregister(ixp_clock.ptp_clock);
+}
+
+static int __init ptp_ixp_init(void)
+{
+	if (!cpu_is_ixp46x())
+		return -ENODEV;
+
+	ixp_clock.regs =
+		(struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT;
+
+	ixp_clock.caps = ptp_ixp_caps;
+
+	ixp_clock.ptp_clock = ptp_clock_register(&ixp_clock.caps);
+
+	if (IS_ERR(ixp_clock.ptp_clock))
+		return PTR_ERR(ixp_clock.ptp_clock);
+
+	__raw_writel(DEFAULT_ADDEND, &ixp_clock.regs->addend);
+	__raw_writel(1, &ixp_clock.regs->trgt_lo);
+	__raw_writel(0, &ixp_clock.regs->trgt_hi);
+	__raw_writel(TTIPEND, &ixp_clock.regs->event);
+
+	if (MASTER_IRQ != setup_interrupt(MASTER_GPIO)) {
+		pr_err("failed to setup gpio %d as irq\n", MASTER_GPIO);
+		goto no_master;
+	}
+	if (SLAVE_IRQ != setup_interrupt(SLAVE_GPIO)) {
+		pr_err("failed to setup gpio %d as irq\n", SLAVE_GPIO);
+		goto no_slave;
+	}
+
+	return 0;
+no_slave:
+	free_irq(MASTER_IRQ, &ixp_clock);
+no_master:
+	ptp_clock_unregister(ixp_clock.ptp_clock);
+	return -ENODEV;
+}
+
+module_init(ptp_ixp_init);
+module_exit(ptp_ixp_exit);
+
+MODULE_AUTHOR("Richard Cochran <richard.cochran@omicron.at>");
+MODULE_DESCRIPTION("PTP clock using the IXP46X timer");
+MODULE_LICENSE("GPL");
-- 
1.7.0.4

^ permalink raw reply related

* [PATCH V15 4/4] ptp: Added a clock driver for the National Semiconductor PHYTER.
From: Richard Cochran @ 2011-04-22 10:04 UTC (permalink / raw)
  To: linux-kernel
  Cc: Thomas Gleixner, Rodolfo Giometti, Arnd Bergmann, Peter Zijlstra,
	linux-api, devicetree-discuss, Russell King, Paul Mackerras,
	John Stultz, linux-arm-kernel, netdev, Ben Hutchings,
	Mike Frysinger, Christoph Lameter, linuxppc-dev, David Miller,
	Alan Cox, Krzysztof Halasa
In-Reply-To: <cover.1303466102.git.richard.cochran@omicron.at>

This patch adds support for the PTP clock found on the DP83640.
The basic clock operations and one external time stamp have
been implemented.

Signed-off-by: Richard Cochran <richard.cochran@omicron.at>
---
 drivers/net/phy/Makefile      |    1 +
 drivers/net/phy/dp83640.c     | 1100 +++++++++++++++++++++++++++++++++++++++++
 drivers/net/phy/dp83640_reg.h |  267 ++++++++++
 drivers/ptp/Kconfig           |   19 +
 4 files changed, 1387 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/phy/dp83640.c
 create mode 100644 drivers/net/phy/dp83640_reg.h

diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 13bebab..2333215 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_FIXED_PHY)		+= fixed.o
 obj-$(CONFIG_MDIO_BITBANG)	+= mdio-bitbang.o
 obj-$(CONFIG_MDIO_GPIO)		+= mdio-gpio.o
 obj-$(CONFIG_NATIONAL_PHY)	+= national.o
+obj-$(CONFIG_DP83640_PHY)	+= dp83640.o
 obj-$(CONFIG_STE10XP)		+= ste10Xp.o
 obj-$(CONFIG_MICREL_PHY)	+= micrel.o
 obj-$(CONFIG_MDIO_OCTEON)	+= mdio-octeon.o
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
new file mode 100644
index 0000000..d463b8a
--- /dev/null
+++ b/drivers/net/phy/dp83640.c
@@ -0,0 +1,1100 @@
+/*
+ * Driver for the National Semiconductor DP83640 PHYTER
+ *
+ * Copyright (C) 2010 OMICRON electronics GmbH
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/ethtool.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mii.h>
+#include <linux/module.h>
+#include <linux/net_tstamp.h>
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+#include <linux/ptp_classify.h>
+#include <linux/ptp_clock_kernel.h>
+
+#include "dp83640_reg.h"
+
+#define DP83640_PHY_ID	0x20005ce1
+#define PAGESEL		0x13
+#define LAYER4		0x02
+#define LAYER2		0x01
+#define MAX_RXTS	4
+#define MAX_TXTS	4
+#define N_EXT_TS	1
+#define PSF_PTPVER	2
+#define PSF_EVNT	0x4000
+#define PSF_RX		0x2000
+#define PSF_TX		0x1000
+#define EXT_EVENT	1
+#define EXT_GPIO	1
+#define CAL_EVENT	2
+#define CAL_GPIO	9
+#define CAL_TRIGGER	2
+
+/* phyter seems to miss the mark by 16 ns */
+#define ADJTIME_FIX	16
+
+#if defined(__BIG_ENDIAN)
+#define ENDIAN_FLAG	0
+#elif defined(__LITTLE_ENDIAN)
+#define ENDIAN_FLAG	PSF_ENDIAN
+#endif
+
+#define SKB_PTP_TYPE(__skb) (*(unsigned int *)((__skb)->cb))
+
+struct phy_rxts {
+	u16 ns_lo;   /* ns[15:0] */
+	u16 ns_hi;   /* overflow[1:0], ns[29:16] */
+	u16 sec_lo;  /* sec[15:0] */
+	u16 sec_hi;  /* sec[31:16] */
+	u16 seqid;   /* sequenceId[15:0] */
+	u16 msgtype; /* messageType[3:0], hash[11:0] */
+};
+
+struct phy_txts {
+	u16 ns_lo;   /* ns[15:0] */
+	u16 ns_hi;   /* overflow[1:0], ns[29:16] */
+	u16 sec_lo;  /* sec[15:0] */
+	u16 sec_hi;  /* sec[31:16] */
+};
+
+struct rxts {
+	struct list_head list;
+	unsigned long tmo;
+	u64 ns;
+	u16 seqid;
+	u8  msgtype;
+	u16 hash;
+};
+
+struct dp83640_clock;
+
+struct dp83640_private {
+	struct list_head list;
+	struct dp83640_clock *clock;
+	struct phy_device *phydev;
+	struct work_struct ts_work;
+	int hwts_tx_en;
+	int hwts_rx_en;
+	int layer;
+	int version;
+	/* remember state of cfg0 during calibration */
+	int cfg0;
+	/* remember the last event time stamp */
+	struct phy_txts edata;
+	/* list of rx timestamps */
+	struct list_head rxts;
+	struct list_head rxpool;
+	struct rxts rx_pool_data[MAX_RXTS];
+	/* protects above three fields from concurrent access */
+	spinlock_t rx_lock;
+	/* queues of incoming and outgoing packets */
+	struct sk_buff_head rx_queue;
+	struct sk_buff_head tx_queue;
+};
+
+struct dp83640_clock {
+	/* keeps the instance in the 'phyter_clocks' list */
+	struct list_head list;
+	/* we create one clock instance per MII bus */
+	struct mii_bus *bus;
+	/* protects extended registers from concurrent access */
+	struct mutex extreg_lock;
+	/* remembers which page was last selected */
+	int page;
+	/* our advertised capabilities */
+	struct ptp_clock_info caps;
+	/* protects the three fields below from concurrent access */
+	struct mutex clock_lock;
+	/* the one phyter from which we shall read */
+	struct dp83640_private *chosen;
+	/* list of the other attached phyters, not chosen */
+	struct list_head phylist;
+	/* reference to our PTP hardware clock */
+	struct ptp_clock *ptp_clock;
+};
+
+/* globals */
+
+static int chosen_phy = -1;
+static ushort cal_gpio = 4;
+
+module_param(chosen_phy, int, 0444);
+module_param(cal_gpio, ushort, 0444);
+
+MODULE_PARM_DESC(chosen_phy, \
+	"The address of the PHY to use for the ancillary clock features");
+MODULE_PARM_DESC(cal_gpio, \
+	"Which GPIO line to use for synchronizing multiple PHYs");
+
+/* a list of clocks and a mutex to protect it */
+static LIST_HEAD(phyter_clocks);
+static DEFINE_MUTEX(phyter_clocks_lock);
+
+static void rx_timestamp_work(struct work_struct *work);
+
+/* extended register access functions */
+
+#define BROADCAST_ADDR 31
+
+static inline int broadcast_write(struct mii_bus *bus, u32 regnum, u16 val)
+{
+	return mdiobus_write(bus, BROADCAST_ADDR, regnum, val);
+}
+
+/* Caller must hold extreg_lock. */
+static int ext_read(struct phy_device *phydev, int page, u32 regnum)
+{
+	struct dp83640_private *dp83640 = phydev->priv;
+	int val;
+
+	if (dp83640->clock->page != page) {
+		broadcast_write(phydev->bus, PAGESEL, page);
+		dp83640->clock->page = page;
+	}
+	val = phy_read(phydev, regnum);
+
+	return val;
+}
+
+/* Caller must hold extreg_lock. */
+static void ext_write(int broadcast, struct phy_device *phydev,
+		      int page, u32 regnum, u16 val)
+{
+	struct dp83640_private *dp83640 = phydev->priv;
+
+	if (dp83640->clock->page != page) {
+		broadcast_write(phydev->bus, PAGESEL, page);
+		dp83640->clock->page = page;
+	}
+	if (broadcast)
+		broadcast_write(phydev->bus, regnum, val);
+	else
+		phy_write(phydev, regnum, val);
+}
+
+/* Caller must hold extreg_lock. */
+static int tdr_write(int bc, struct phy_device *dev,
+		     const struct timespec *ts, u16 cmd)
+{
+	ext_write(bc, dev, PAGE4, PTP_TDR, ts->tv_nsec & 0xffff);/* ns[15:0]  */
+	ext_write(bc, dev, PAGE4, PTP_TDR, ts->tv_nsec >> 16);   /* ns[31:16] */
+	ext_write(bc, dev, PAGE4, PTP_TDR, ts->tv_sec & 0xffff); /* sec[15:0] */
+	ext_write(bc, dev, PAGE4, PTP_TDR, ts->tv_sec >> 16);    /* sec[31:16]*/
+
+	ext_write(bc, dev, PAGE4, PTP_CTL, cmd);
+
+	return 0;
+}
+
+/* convert phy timestamps into driver timestamps */
+
+static void phy2rxts(struct phy_rxts *p, struct rxts *rxts)
+{
+	u32 sec;
+
+	sec = p->sec_lo;
+	sec |= p->sec_hi << 16;
+
+	rxts->ns = p->ns_lo;
+	rxts->ns |= (p->ns_hi & 0x3fff) << 16;
+	rxts->ns += ((u64)sec) * 1000000000ULL;
+	rxts->seqid = p->seqid;
+	rxts->msgtype = (p->msgtype >> 12) & 0xf;
+	rxts->hash = p->msgtype & 0x0fff;
+	rxts->tmo = jiffies + HZ;
+}
+
+static u64 phy2txts(struct phy_txts *p)
+{
+	u64 ns;
+	u32 sec;
+
+	sec = p->sec_lo;
+	sec |= p->sec_hi << 16;
+
+	ns = p->ns_lo;
+	ns |= (p->ns_hi & 0x3fff) << 16;
+	ns += ((u64)sec) * 1000000000ULL;
+
+	return ns;
+}
+
+/* ptp clock methods */
+
+static int ptp_dp83640_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+	struct dp83640_clock *clock =
+		container_of(ptp, struct dp83640_clock, caps);
+	struct phy_device *phydev = clock->chosen->phydev;
+	u64 rate;
+	int neg_adj = 0;
+	u16 hi, lo;
+
+	if (ppb < 0) {
+		neg_adj = 1;
+		ppb = -ppb;
+	}
+	rate = ppb;
+	rate <<= 26;
+	rate = div_u64(rate, 1953125);
+
+	hi = (rate >> 16) & PTP_RATE_HI_MASK;
+	if (neg_adj)
+		hi |= PTP_RATE_DIR;
+
+	lo = rate & 0xffff;
+
+	mutex_lock(&clock->extreg_lock);
+
+	ext_write(1, phydev, PAGE4, PTP_RATEH, hi);
+	ext_write(1, phydev, PAGE4, PTP_RATEL, lo);
+
+	mutex_unlock(&clock->extreg_lock);
+
+	return 0;
+}
+
+static int ptp_dp83640_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+	struct dp83640_clock *clock =
+		container_of(ptp, struct dp83640_clock, caps);
+	struct phy_device *phydev = clock->chosen->phydev;
+	struct timespec ts;
+	int err;
+
+	delta += ADJTIME_FIX;
+
+	ts = ns_to_timespec(delta);
+
+	mutex_lock(&clock->extreg_lock);
+
+	err = tdr_write(1, phydev, &ts, PTP_STEP_CLK);
+
+	mutex_unlock(&clock->extreg_lock);
+
+	return err;
+}
+
+static int ptp_dp83640_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+	struct dp83640_clock *clock =
+		container_of(ptp, struct dp83640_clock, caps);
+	struct phy_device *phydev = clock->chosen->phydev;
+	unsigned int val[4];
+
+	mutex_lock(&clock->extreg_lock);
+
+	ext_write(0, phydev, PAGE4, PTP_CTL, PTP_RD_CLK);
+
+	val[0] = ext_read(phydev, PAGE4, PTP_TDR); /* ns[15:0] */
+	val[1] = ext_read(phydev, PAGE4, PTP_TDR); /* ns[31:16] */
+	val[2] = ext_read(phydev, PAGE4, PTP_TDR); /* sec[15:0] */
+	val[3] = ext_read(phydev, PAGE4, PTP_TDR); /* sec[31:16] */
+
+	mutex_unlock(&clock->extreg_lock);
+
+	ts->tv_nsec = val[0] | (val[1] << 16);
+	ts->tv_sec  = val[2] | (val[3] << 16);
+
+	return 0;
+}
+
+static int ptp_dp83640_settime(struct ptp_clock_info *ptp,
+			       const struct timespec *ts)
+{
+	struct dp83640_clock *clock =
+		container_of(ptp, struct dp83640_clock, caps);
+	struct phy_device *phydev = clock->chosen->phydev;
+	int err;
+
+	mutex_lock(&clock->extreg_lock);
+
+	err = tdr_write(1, phydev, ts, PTP_LOAD_CLK);
+
+	mutex_unlock(&clock->extreg_lock);
+
+	return err;
+}
+
+static int ptp_dp83640_enable(struct ptp_clock_info *ptp,
+			      struct ptp_clock_request *rq, int on)
+{
+	struct dp83640_clock *clock =
+		container_of(ptp, struct dp83640_clock, caps);
+	struct phy_device *phydev = clock->chosen->phydev;
+	u16 evnt;
+
+	switch (rq->type) {
+	case PTP_CLK_REQ_EXTTS:
+		if (rq->extts.index != 0)
+			return -EINVAL;
+		evnt = EVNT_WR | (EXT_EVENT & EVNT_SEL_MASK) << EVNT_SEL_SHIFT;
+		if (on) {
+			evnt |= (EXT_GPIO & EVNT_GPIO_MASK) << EVNT_GPIO_SHIFT;
+			evnt |= EVNT_RISE;
+		}
+		ext_write(0, phydev, PAGE5, PTP_EVNT, evnt);
+		return 0;
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static u8 status_frame_dst[6] = { 0x01, 0x1B, 0x19, 0x00, 0x00, 0x00 };
+static u8 status_frame_src[6] = { 0x08, 0x00, 0x17, 0x0B, 0x6B, 0x0F };
+
+static void enable_status_frames(struct phy_device *phydev, bool on)
+{
+	u16 cfg0 = 0, ver;
+
+	if (on)
+		cfg0 = PSF_EVNT_EN | PSF_RXTS_EN | PSF_TXTS_EN | ENDIAN_FLAG;
+
+	ver = (PSF_PTPVER & VERSIONPTP_MASK) << VERSIONPTP_SHIFT;
+
+	ext_write(0, phydev, PAGE5, PSF_CFG0, cfg0);
+	ext_write(0, phydev, PAGE6, PSF_CFG1, ver);
+
+	if (!phydev->attached_dev) {
+		pr_warning("dp83640: expected to find an attached netdevice\n");
+		return;
+	}
+
+	if (on) {
+		if (dev_mc_add(phydev->attached_dev, status_frame_dst))
+			pr_warning("dp83640: failed to add mc address\n");
+	} else {
+		if (dev_mc_del(phydev->attached_dev, status_frame_dst))
+			pr_warning("dp83640: failed to delete mc address\n");
+	}
+}
+
+static bool is_status_frame(struct sk_buff *skb, int type)
+{
+	struct ethhdr *h = eth_hdr(skb);
+
+	if (PTP_CLASS_V2_L2 == type &&
+	    !memcmp(h->h_source, status_frame_src, sizeof(status_frame_src)))
+		return true;
+	else
+		return false;
+}
+
+static int expired(struct rxts *rxts)
+{
+	return time_after(jiffies, rxts->tmo);
+}
+
+/* Caller must hold rx_lock. */
+static void prune_rx_ts(struct dp83640_private *dp83640)
+{
+	struct list_head *this, *next;
+	struct rxts *rxts;
+
+	list_for_each_safe(this, next, &dp83640->rxts) {
+		rxts = list_entry(this, struct rxts, list);
+		if (expired(rxts)) {
+			list_del_init(&rxts->list);
+			list_add(&rxts->list, &dp83640->rxpool);
+		}
+	}
+}
+
+/* synchronize the phyters so they act as one clock */
+
+static void enable_broadcast(struct phy_device *phydev, int init_page, int on)
+{
+	int val;
+	phy_write(phydev, PAGESEL, 0);
+	val = phy_read(phydev, PHYCR2);
+	if (on)
+		val |= BC_WRITE;
+	else
+		val &= ~BC_WRITE;
+	phy_write(phydev, PHYCR2, val);
+	phy_write(phydev, PAGESEL, init_page);
+}
+
+static void recalibrate(struct dp83640_clock *clock)
+{
+	s64 now, diff;
+	struct phy_txts event_ts;
+	struct timespec ts;
+	struct list_head *this;
+	struct dp83640_private *tmp;
+	struct phy_device *master = clock->chosen->phydev;
+	u16 cfg0, evnt, ptp_trig, trigger, val;
+
+	trigger = CAL_TRIGGER;
+
+	mutex_lock(&clock->extreg_lock);
+
+	/*
+	 * enable broadcast, disable status frames, enable ptp clock
+	 */
+	list_for_each(this, &clock->phylist) {
+		tmp = list_entry(this, struct dp83640_private, list);
+		enable_broadcast(tmp->phydev, clock->page, 1);
+		tmp->cfg0 = ext_read(tmp->phydev, PAGE5, PSF_CFG0);
+		ext_write(0, tmp->phydev, PAGE5, PSF_CFG0, 0);
+		ext_write(0, tmp->phydev, PAGE4, PTP_CTL, PTP_ENABLE);
+	}
+	enable_broadcast(master, clock->page, 1);
+	cfg0 = ext_read(master, PAGE5, PSF_CFG0);
+	ext_write(0, master, PAGE5, PSF_CFG0, 0);
+	ext_write(0, master, PAGE4, PTP_CTL, PTP_ENABLE);
+
+	/*
+	 * enable an event timestamp
+	 */
+	evnt = EVNT_WR | EVNT_RISE | EVNT_SINGLE;
+	evnt |= (CAL_EVENT & EVNT_SEL_MASK) << EVNT_SEL_SHIFT;
+	evnt |= (cal_gpio & EVNT_GPIO_MASK) << EVNT_GPIO_SHIFT;
+
+	list_for_each(this, &clock->phylist) {
+		tmp = list_entry(this, struct dp83640_private, list);
+		ext_write(0, tmp->phydev, PAGE5, PTP_EVNT, evnt);
+	}
+	ext_write(0, master, PAGE5, PTP_EVNT, evnt);
+
+	/*
+	 * configure a trigger
+	 */
+	ptp_trig = TRIG_WR | TRIG_IF_LATE | TRIG_PULSE;
+	ptp_trig |= (trigger  & TRIG_CSEL_MASK) << TRIG_CSEL_SHIFT;
+	ptp_trig |= (cal_gpio & TRIG_GPIO_MASK) << TRIG_GPIO_SHIFT;
+	ext_write(0, master, PAGE5, PTP_TRIG, ptp_trig);
+
+	/* load trigger */
+	val = (trigger & TRIG_SEL_MASK) << TRIG_SEL_SHIFT;
+	val |= TRIG_LOAD;
+	ext_write(0, master, PAGE4, PTP_CTL, val);
+
+	/* enable trigger */
+	val &= ~TRIG_LOAD;
+	val |= TRIG_EN;
+	ext_write(0, master, PAGE4, PTP_CTL, val);
+
+	/* disable trigger */
+	val = (trigger & TRIG_SEL_MASK) << TRIG_SEL_SHIFT;
+	val |= TRIG_DIS;
+	ext_write(0, master, PAGE4, PTP_CTL, val);
+
+	/*
+	 * read out and correct offsets
+	 */
+	val = ext_read(master, PAGE4, PTP_STS);
+	pr_info("master PTP_STS  0x%04hx", val);
+	val = ext_read(master, PAGE4, PTP_ESTS);
+	pr_info("master PTP_ESTS 0x%04hx", val);
+	event_ts.ns_lo  = ext_read(master, PAGE4, PTP_EDATA);
+	event_ts.ns_hi  = ext_read(master, PAGE4, PTP_EDATA);
+	event_ts.sec_lo = ext_read(master, PAGE4, PTP_EDATA);
+	event_ts.sec_hi = ext_read(master, PAGE4, PTP_EDATA);
+	now = phy2txts(&event_ts);
+
+	list_for_each(this, &clock->phylist) {
+		tmp = list_entry(this, struct dp83640_private, list);
+		val = ext_read(tmp->phydev, PAGE4, PTP_STS);
+		pr_info("slave  PTP_STS  0x%04hx", val);
+		val = ext_read(tmp->phydev, PAGE4, PTP_ESTS);
+		pr_info("slave  PTP_ESTS 0x%04hx", val);
+		event_ts.ns_lo  = ext_read(tmp->phydev, PAGE4, PTP_EDATA);
+		event_ts.ns_hi  = ext_read(tmp->phydev, PAGE4, PTP_EDATA);
+		event_ts.sec_lo = ext_read(tmp->phydev, PAGE4, PTP_EDATA);
+		event_ts.sec_hi = ext_read(tmp->phydev, PAGE4, PTP_EDATA);
+		diff = now - (s64) phy2txts(&event_ts);
+		pr_info("slave offset %lld nanoseconds\n", diff);
+		diff += ADJTIME_FIX;
+		ts = ns_to_timespec(diff);
+		tdr_write(0, tmp->phydev, &ts, PTP_STEP_CLK);
+	}
+
+	/*
+	 * restore status frames
+	 */
+	list_for_each(this, &clock->phylist) {
+		tmp = list_entry(this, struct dp83640_private, list);
+		ext_write(0, tmp->phydev, PAGE5, PSF_CFG0, tmp->cfg0);
+	}
+	ext_write(0, master, PAGE5, PSF_CFG0, cfg0);
+
+	mutex_unlock(&clock->extreg_lock);
+}
+
+/* time stamping methods */
+
+static void decode_evnt(struct dp83640_private *dp83640,
+			struct phy_txts *phy_txts, u16 ests)
+{
+	struct ptp_clock_event event;
+	int words = (ests >> EVNT_TS_LEN_SHIFT) & EVNT_TS_LEN_MASK;
+
+	switch (words) { /* fall through in every case */
+	case 3:
+		dp83640->edata.sec_hi = phy_txts->sec_hi;
+	case 2:
+		dp83640->edata.sec_lo = phy_txts->sec_lo;
+	case 1:
+		dp83640->edata.ns_hi = phy_txts->ns_hi;
+	case 0:
+		dp83640->edata.ns_lo = phy_txts->ns_lo;
+	}
+
+	event.type = PTP_CLOCK_EXTTS;
+	event.index = 0;
+	event.timestamp = phy2txts(&dp83640->edata);
+
+	ptp_clock_event(dp83640->clock->ptp_clock, &event);
+}
+
+static void decode_rxts(struct dp83640_private *dp83640,
+			struct phy_rxts *phy_rxts)
+{
+	struct rxts *rxts;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dp83640->rx_lock, flags);
+
+	prune_rx_ts(dp83640);
+
+	if (list_empty(&dp83640->rxpool)) {
+		pr_warning("dp83640: rx timestamp pool is empty\n");
+		goto out;
+	}
+	rxts = list_first_entry(&dp83640->rxpool, struct rxts, list);
+	list_del_init(&rxts->list);
+	phy2rxts(phy_rxts, rxts);
+	list_add_tail(&rxts->list, &dp83640->rxts);
+out:
+	spin_unlock_irqrestore(&dp83640->rx_lock, flags);
+}
+
+static void decode_txts(struct dp83640_private *dp83640,
+			struct phy_txts *phy_txts)
+{
+	struct skb_shared_hwtstamps shhwtstamps;
+	struct sk_buff *skb;
+	u64 ns;
+
+	/* We must already have the skb that triggered this. */
+
+	skb = skb_dequeue(&dp83640->tx_queue);
+
+	if (!skb) {
+		pr_warning("dp83640: have timestamp but tx_queue empty\n");
+		return;
+	}
+	ns = phy2txts(phy_txts);
+	memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+	shhwtstamps.hwtstamp = ns_to_ktime(ns);
+	skb_complete_tx_timestamp(skb, &shhwtstamps);
+}
+
+static void decode_status_frame(struct dp83640_private *dp83640,
+				struct sk_buff *skb)
+{
+	struct phy_rxts *phy_rxts;
+	struct phy_txts *phy_txts;
+	u8 *ptr;
+	int len, size;
+	u16 ests, type;
+
+	ptr = skb->data + 2;
+
+	for (len = skb_headlen(skb) - 2; len > sizeof(type); len -= size) {
+
+		type = *(u16 *)ptr;
+		ests = type & 0x0fff;
+		type = type & 0xf000;
+		len -= sizeof(type);
+		ptr += sizeof(type);
+
+		if (PSF_RX == type && len >= sizeof(*phy_rxts)) {
+
+			phy_rxts = (struct phy_rxts *) ptr;
+			decode_rxts(dp83640, phy_rxts);
+			size = sizeof(*phy_rxts);
+
+		} else if (PSF_TX == type && len >= sizeof(*phy_txts)) {
+
+			phy_txts = (struct phy_txts *) ptr;
+			decode_txts(dp83640, phy_txts);
+			size = sizeof(*phy_txts);
+
+		} else if (PSF_EVNT == type && len >= sizeof(*phy_txts)) {
+
+			phy_txts = (struct phy_txts *) ptr;
+			decode_evnt(dp83640, phy_txts, ests);
+			size = sizeof(*phy_txts);
+
+		} else {
+			size = 0;
+			break;
+		}
+		ptr += size;
+	}
+}
+
+static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts)
+{
+	u16 *seqid;
+	unsigned int offset;
+	u8 *msgtype, *data = skb_mac_header(skb);
+
+	/* check sequenceID, messageType, 12 bit hash of offset 20-29 */
+
+	switch (type) {
+	case PTP_CLASS_V1_IPV4:
+	case PTP_CLASS_V2_IPV4:
+		offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
+		break;
+	case PTP_CLASS_V1_IPV6:
+	case PTP_CLASS_V2_IPV6:
+		offset = OFF_PTP6;
+		break;
+	case PTP_CLASS_V2_L2:
+		offset = ETH_HLEN;
+		break;
+	case PTP_CLASS_V2_VLAN:
+		offset = ETH_HLEN + VLAN_HLEN;
+		break;
+	default:
+		return 0;
+	}
+
+	if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID + sizeof(*seqid))
+		return 0;
+
+	if (unlikely(type & PTP_CLASS_V1))
+		msgtype = data + offset + OFF_PTP_CONTROL;
+	else
+		msgtype = data + offset;
+
+	seqid = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
+
+	return (rxts->msgtype == (*msgtype & 0xf) &&
+		rxts->seqid   == ntohs(*seqid));
+}
+
+static void dp83640_free_clocks(void)
+{
+	struct dp83640_clock *clock;
+	struct list_head *this, *next;
+
+	mutex_lock(&phyter_clocks_lock);
+
+	list_for_each_safe(this, next, &phyter_clocks) {
+		clock = list_entry(this, struct dp83640_clock, list);
+		if (!list_empty(&clock->phylist)) {
+			pr_warning("phy list non-empty while unloading");
+			BUG();
+		}
+		list_del(&clock->list);
+		mutex_destroy(&clock->extreg_lock);
+		mutex_destroy(&clock->clock_lock);
+		put_device(&clock->bus->dev);
+		kfree(clock);
+	}
+
+	mutex_unlock(&phyter_clocks_lock);
+}
+
+static void dp83640_clock_init(struct dp83640_clock *clock, struct mii_bus *bus)
+{
+	INIT_LIST_HEAD(&clock->list);
+	clock->bus = bus;
+	mutex_init(&clock->extreg_lock);
+	mutex_init(&clock->clock_lock);
+	INIT_LIST_HEAD(&clock->phylist);
+	clock->caps.owner = THIS_MODULE;
+	sprintf(clock->caps.name, "dp83640 timer");
+	clock->caps.max_adj	= 1953124;
+	clock->caps.n_alarm	= 0;
+	clock->caps.n_ext_ts	= N_EXT_TS;
+	clock->caps.n_per_out	= 0;
+	clock->caps.pps		= 0;
+	clock->caps.adjfreq	= ptp_dp83640_adjfreq;
+	clock->caps.adjtime	= ptp_dp83640_adjtime;
+	clock->caps.gettime	= ptp_dp83640_gettime;
+	clock->caps.settime	= ptp_dp83640_settime;
+	clock->caps.enable	= ptp_dp83640_enable;
+	/*
+	 * Get a reference to this bus instance.
+	 */
+	get_device(&bus->dev);
+}
+
+static int choose_this_phy(struct dp83640_clock *clock,
+			   struct phy_device *phydev)
+{
+	if (chosen_phy == -1 && !clock->chosen)
+		return 1;
+
+	if (chosen_phy == phydev->addr)
+		return 1;
+
+	return 0;
+}
+
+static struct dp83640_clock *dp83640_clock_get(struct dp83640_clock *clock)
+{
+	if (clock)
+		mutex_lock(&clock->clock_lock);
+	return clock;
+}
+
+/*
+ * Look up and lock a clock by bus instance.
+ * If there is no clock for this bus, then create it first.
+ */
+static struct dp83640_clock *dp83640_clock_get_bus(struct mii_bus *bus)
+{
+	struct dp83640_clock *clock = NULL, *tmp;
+	struct list_head *this;
+
+	mutex_lock(&phyter_clocks_lock);
+
+	list_for_each(this, &phyter_clocks) {
+		tmp = list_entry(this, struct dp83640_clock, list);
+		if (tmp->bus == bus) {
+			clock = tmp;
+			break;
+		}
+	}
+	if (clock)
+		goto out;
+
+	clock = kzalloc(sizeof(struct dp83640_clock), GFP_KERNEL);
+	if (!clock)
+		goto out;
+
+	dp83640_clock_init(clock, bus);
+	list_add_tail(&phyter_clocks, &clock->list);
+out:
+	mutex_unlock(&phyter_clocks_lock);
+
+	return dp83640_clock_get(clock);
+}
+
+static void dp83640_clock_put(struct dp83640_clock *clock)
+{
+	mutex_unlock(&clock->clock_lock);
+}
+
+static int dp83640_probe(struct phy_device *phydev)
+{
+	struct dp83640_clock *clock;
+	struct dp83640_private *dp83640;
+	int err = -ENOMEM, i;
+
+	if (phydev->addr == BROADCAST_ADDR)
+		return 0;
+
+	clock = dp83640_clock_get_bus(phydev->bus);
+	if (!clock)
+		goto no_clock;
+
+	dp83640 = kzalloc(sizeof(struct dp83640_private), GFP_KERNEL);
+	if (!dp83640)
+		goto no_memory;
+
+	dp83640->phydev = phydev;
+	INIT_WORK(&dp83640->ts_work, rx_timestamp_work);
+
+	INIT_LIST_HEAD(&dp83640->rxts);
+	INIT_LIST_HEAD(&dp83640->rxpool);
+	for (i = 0; i < MAX_RXTS; i++)
+		list_add(&dp83640->rx_pool_data[i].list, &dp83640->rxpool);
+
+	phydev->priv = dp83640;
+
+	spin_lock_init(&dp83640->rx_lock);
+	skb_queue_head_init(&dp83640->rx_queue);
+	skb_queue_head_init(&dp83640->tx_queue);
+
+	dp83640->clock = clock;
+
+	if (choose_this_phy(clock, phydev)) {
+		clock->chosen = dp83640;
+		clock->ptp_clock = ptp_clock_register(&clock->caps);
+		if (IS_ERR(clock->ptp_clock)) {
+			err = PTR_ERR(clock->ptp_clock);
+			goto no_register;
+		}
+	} else
+		list_add_tail(&dp83640->list, &clock->phylist);
+
+	if (clock->chosen && !list_empty(&clock->phylist))
+		recalibrate(clock);
+	else
+		enable_broadcast(dp83640->phydev, clock->page, 1);
+
+	dp83640_clock_put(clock);
+	return 0;
+
+no_register:
+	clock->chosen = NULL;
+	kfree(dp83640);
+no_memory:
+	dp83640_clock_put(clock);
+no_clock:
+	return err;
+}
+
+static void dp83640_remove(struct phy_device *phydev)
+{
+	struct dp83640_clock *clock;
+	struct list_head *this, *next;
+	struct dp83640_private *tmp, *dp83640 = phydev->priv;
+
+	if (phydev->addr == BROADCAST_ADDR)
+		return;
+
+	enable_status_frames(phydev, false);
+	cancel_work_sync(&dp83640->ts_work);
+
+	clock = dp83640_clock_get(dp83640->clock);
+
+	if (dp83640 == clock->chosen) {
+		ptp_clock_unregister(clock->ptp_clock);
+		clock->chosen = NULL;
+	} else {
+		list_for_each_safe(this, next, &clock->phylist) {
+			tmp = list_entry(this, struct dp83640_private, list);
+			if (tmp == dp83640) {
+				list_del_init(&tmp->list);
+				break;
+			}
+		}
+	}
+
+	dp83640_clock_put(clock);
+	kfree(dp83640);
+}
+
+static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
+{
+	struct dp83640_private *dp83640 = phydev->priv;
+	struct hwtstamp_config cfg;
+	u16 txcfg0, rxcfg0;
+
+	if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
+		return -EFAULT;
+
+	if (cfg.flags) /* reserved for future extensions */
+		return -EINVAL;
+
+	switch (cfg.tx_type) {
+	case HWTSTAMP_TX_OFF:
+		dp83640->hwts_tx_en = 0;
+		break;
+	case HWTSTAMP_TX_ON:
+		dp83640->hwts_tx_en = 1;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	switch (cfg.rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		dp83640->hwts_rx_en = 0;
+		dp83640->layer = 0;
+		dp83640->version = 0;
+		break;
+	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+		dp83640->hwts_rx_en = 1;
+		dp83640->layer = LAYER4;
+		dp83640->version = 1;
+		break;
+	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+		dp83640->hwts_rx_en = 1;
+		dp83640->layer = LAYER4;
+		dp83640->version = 2;
+		break;
+	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+		dp83640->hwts_rx_en = 1;
+		dp83640->layer = LAYER2;
+		dp83640->version = 2;
+		break;
+	case HWTSTAMP_FILTER_PTP_V2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+		dp83640->hwts_rx_en = 1;
+		dp83640->layer = LAYER4|LAYER2;
+		dp83640->version = 2;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	txcfg0 = (dp83640->version & TX_PTP_VER_MASK) << TX_PTP_VER_SHIFT;
+	rxcfg0 = (dp83640->version & TX_PTP_VER_MASK) << TX_PTP_VER_SHIFT;
+
+	if (dp83640->layer & LAYER2) {
+		txcfg0 |= TX_L2_EN;
+		rxcfg0 |= RX_L2_EN;
+	}
+	if (dp83640->layer & LAYER4) {
+		txcfg0 |= TX_IPV6_EN | TX_IPV4_EN;
+		rxcfg0 |= RX_IPV6_EN | RX_IPV4_EN;
+	}
+
+	if (dp83640->hwts_tx_en)
+		txcfg0 |= TX_TS_EN;
+
+	if (dp83640->hwts_rx_en)
+		rxcfg0 |= RX_TS_EN;
+
+	mutex_lock(&dp83640->clock->extreg_lock);
+
+	if (dp83640->hwts_tx_en || dp83640->hwts_rx_en) {
+		enable_status_frames(phydev, true);
+		ext_write(0, phydev, PAGE4, PTP_CTL, PTP_ENABLE);
+	}
+
+	ext_write(0, phydev, PAGE5, PTP_TXCFG0, txcfg0);
+	ext_write(0, phydev, PAGE5, PTP_RXCFG0, rxcfg0);
+
+	mutex_unlock(&dp83640->clock->extreg_lock);
+
+	return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
+}
+
+static void rx_timestamp_work(struct work_struct *work)
+{
+	struct dp83640_private *dp83640 =
+		container_of(work, struct dp83640_private, ts_work);
+	struct list_head *this, *next;
+	struct rxts *rxts;
+	struct skb_shared_hwtstamps *shhwtstamps;
+	struct sk_buff *skb;
+	unsigned int type;
+	unsigned long flags;
+
+	/* Deliver each deferred packet, with or without a time stamp. */
+
+	while ((skb = skb_dequeue(&dp83640->rx_queue)) != NULL) {
+		type = SKB_PTP_TYPE(skb);
+		spin_lock_irqsave(&dp83640->rx_lock, flags);
+		list_for_each_safe(this, next, &dp83640->rxts) {
+			rxts = list_entry(this, struct rxts, list);
+			if (match(skb, type, rxts)) {
+				shhwtstamps = skb_hwtstamps(skb);
+				memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+				shhwtstamps->hwtstamp = ns_to_ktime(rxts->ns);
+				list_del_init(&rxts->list);
+				list_add(&rxts->list, &dp83640->rxpool);
+				break;
+			}
+		}
+		spin_unlock_irqrestore(&dp83640->rx_lock, flags);
+		netif_rx(skb);
+	}
+
+	/* Clear out expired time stamps. */
+
+	spin_lock_irqsave(&dp83640->rx_lock, flags);
+	prune_rx_ts(dp83640);
+	spin_unlock_irqrestore(&dp83640->rx_lock, flags);
+}
+
+static bool dp83640_rxtstamp(struct phy_device *phydev,
+			     struct sk_buff *skb, int type)
+{
+	struct dp83640_private *dp83640 = phydev->priv;
+
+	if (!dp83640->hwts_rx_en)
+		return false;
+
+	if (is_status_frame(skb, type)) {
+		decode_status_frame(dp83640, skb);
+		/* Let the stack drop this frame. */
+		return false;
+	}
+
+	SKB_PTP_TYPE(skb) = type;
+	skb_queue_tail(&dp83640->rx_queue, skb);
+	schedule_work(&dp83640->ts_work);
+
+	return true;
+}
+
+static void dp83640_txtstamp(struct phy_device *phydev,
+			     struct sk_buff *skb, int type)
+{
+	struct dp83640_private *dp83640 = phydev->priv;
+
+	if (!dp83640->hwts_tx_en) {
+		kfree_skb(skb);
+		return;
+	}
+	skb_queue_tail(&dp83640->tx_queue, skb);
+	schedule_work(&dp83640->ts_work);
+}
+
+static struct phy_driver dp83640_driver = {
+	.phy_id		= DP83640_PHY_ID,
+	.phy_id_mask	= 0xfffffff0,
+	.name		= "NatSemi DP83640",
+	.features	= PHY_BASIC_FEATURES,
+	.flags		= 0,
+	.probe		= dp83640_probe,
+	.remove		= dp83640_remove,
+	.config_aneg	= genphy_config_aneg,
+	.read_status	= genphy_read_status,
+	.hwtstamp	= dp83640_hwtstamp,
+	.rxtstamp	= dp83640_rxtstamp,
+	.txtstamp	= dp83640_txtstamp,
+	.driver		= {.owner = THIS_MODULE,}
+};
+
+static int __init dp83640_init(void)
+{
+	return phy_driver_register(&dp83640_driver);
+}
+
+static void __exit dp83640_exit(void)
+{
+	dp83640_free_clocks();
+	phy_driver_unregister(&dp83640_driver);
+}
+
+MODULE_DESCRIPTION("National Semiconductor DP83640 PHY driver");
+MODULE_AUTHOR("Richard Cochran <richard.cochran@omicron.at>");
+MODULE_LICENSE("GPL");
+
+module_init(dp83640_init);
+module_exit(dp83640_exit);
+
+static struct mdio_device_id dp83640_tbl[] = {
+	{ DP83640_PHY_ID, 0xfffffff0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(mdio, dp83640_tbl);
diff --git a/drivers/net/phy/dp83640_reg.h b/drivers/net/phy/dp83640_reg.h
new file mode 100644
index 0000000..e7fe411
--- /dev/null
+++ b/drivers/net/phy/dp83640_reg.h
@@ -0,0 +1,267 @@
+/* dp83640_reg.h
+ * Generated by regen.tcl on Thu Feb 17 10:02:48 AM CET 2011
+ */
+#ifndef HAVE_DP83640_REGISTERS
+#define HAVE_DP83640_REGISTERS
+
+#define PAGE0                     0x0000
+#define PHYCR2                    0x001c /* PHY Control Register 2 */
+
+#define PAGE4                     0x0004
+#define PTP_CTL                   0x0014 /* PTP Control Register */
+#define PTP_TDR                   0x0015 /* PTP Time Data Register */
+#define PTP_STS                   0x0016 /* PTP Status Register */
+#define PTP_TSTS                  0x0017 /* PTP Trigger Status Register */
+#define PTP_RATEL                 0x0018 /* PTP Rate Low Register */
+#define PTP_RATEH                 0x0019 /* PTP Rate High Register */
+#define PTP_RDCKSUM               0x001a /* PTP Read Checksum */
+#define PTP_WRCKSUM               0x001b /* PTP Write Checksum */
+#define PTP_TXTS                  0x001c /* PTP Transmit Timestamp Register, in four 16-bit reads */
+#define PTP_RXTS                  0x001d /* PTP Receive Timestamp Register, in six? 16-bit reads */
+#define PTP_ESTS                  0x001e /* PTP Event Status Register */
+#define PTP_EDATA                 0x001f /* PTP Event Data Register */
+
+#define PAGE5                     0x0005
+#define PTP_TRIG                  0x0014 /* PTP Trigger Configuration Register */
+#define PTP_EVNT                  0x0015 /* PTP Event Configuration Register */
+#define PTP_TXCFG0                0x0016 /* PTP Transmit Configuration Register 0 */
+#define PTP_TXCFG1                0x0017 /* PTP Transmit Configuration Register 1 */
+#define PSF_CFG0                  0x0018 /* PHY Status Frame Configuration Register 0 */
+#define PTP_RXCFG0                0x0019 /* PTP Receive Configuration Register 0 */
+#define PTP_RXCFG1                0x001a /* PTP Receive Configuration Register 1 */
+#define PTP_RXCFG2                0x001b /* PTP Receive Configuration Register 2 */
+#define PTP_RXCFG3                0x001c /* PTP Receive Configuration Register 3 */
+#define PTP_RXCFG4                0x001d /* PTP Receive Configuration Register 4 */
+#define PTP_TRDL                  0x001e /* PTP Temporary Rate Duration Low Register */
+#define PTP_TRDH                  0x001f /* PTP Temporary Rate Duration High Register */
+
+#define PAGE6                     0x0006
+#define PTP_COC                   0x0014 /* PTP Clock Output Control Register */
+#define PSF_CFG1                  0x0015 /* PHY Status Frame Configuration Register 1 */
+#define PSF_CFG2                  0x0016 /* PHY Status Frame Configuration Register 2 */
+#define PSF_CFG3                  0x0017 /* PHY Status Frame Configuration Register 3 */
+#define PSF_CFG4                  0x0018 /* PHY Status Frame Configuration Register 4 */
+#define PTP_SFDCFG                0x0019 /* PTP SFD Configuration Register */
+#define PTP_INTCTL                0x001a /* PTP Interrupt Control Register */
+#define PTP_CLKSRC                0x001b /* PTP Clock Source Register */
+#define PTP_ETR                   0x001c /* PTP Ethernet Type Register */
+#define PTP_OFF                   0x001d /* PTP Offset Register */
+#define PTP_GPIOMON               0x001e /* PTP GPIO Monitor Register */
+#define PTP_RXHASH                0x001f /* PTP Receive Hash Register */
+
+/* Bit definitions for the PHYCR2 register */
+#define BC_WRITE                  (1<<11) /* Broadcast Write Enable */
+
+/* Bit definitions for the PTP_CTL register */
+#define TRIG_SEL_SHIFT            (10)    /* PTP Trigger Select */
+#define TRIG_SEL_MASK             (0x7)
+#define TRIG_DIS                  (1<<9)  /* Disable PTP Trigger */
+#define TRIG_EN                   (1<<8)  /* Enable PTP Trigger */
+#define TRIG_READ                 (1<<7)  /* Read PTP Trigger */
+#define TRIG_LOAD                 (1<<6)  /* Load PTP Trigger */
+#define PTP_RD_CLK                (1<<5)  /* Read PTP Clock */
+#define PTP_LOAD_CLK              (1<<4)  /* Load PTP Clock */
+#define PTP_STEP_CLK              (1<<3)  /* Step PTP Clock */
+#define PTP_ENABLE                (1<<2)  /* Enable PTP Clock */
+#define PTP_DISABLE               (1<<1)  /* Disable PTP Clock */
+#define PTP_RESET                 (1<<0)  /* Reset PTP Clock */
+
+/* Bit definitions for the PTP_STS register */
+#define TXTS_RDY                  (1<<11) /* Transmit Timestamp Ready */
+#define RXTS_RDY                  (1<<10) /* Receive Timestamp Ready */
+#define TRIG_DONE                 (1<<9)  /* PTP Trigger Done */
+#define EVENT_RDY                 (1<<8)  /* PTP Event Timestamp Ready */
+#define TXTS_IE                   (1<<3)  /* Transmit Timestamp Interrupt Enable */
+#define RXTS_IE                   (1<<2)  /* Receive Timestamp Interrupt Enable */
+#define TRIG_IE                   (1<<1)  /* Trigger Interrupt Enable */
+#define EVENT_IE                  (1<<0)  /* Event Interrupt Enable */
+
+/* Bit definitions for the PTP_TSTS register */
+#define TRIG7_ERROR               (1<<15) /* Trigger 7 Error */
+#define TRIG7_ACTIVE              (1<<14) /* Trigger 7 Active */
+#define TRIG6_ERROR               (1<<13) /* Trigger 6 Error */
+#define TRIG6_ACTIVE              (1<<12) /* Trigger 6 Active */
+#define TRIG5_ERROR               (1<<11) /* Trigger 5 Error */
+#define TRIG5_ACTIVE              (1<<10) /* Trigger 5 Active */
+#define TRIG4_ERROR               (1<<9)  /* Trigger 4 Error */
+#define TRIG4_ACTIVE              (1<<8)  /* Trigger 4 Active */
+#define TRIG3_ERROR               (1<<7)  /* Trigger 3 Error */
+#define TRIG3_ACTIVE              (1<<6)  /* Trigger 3 Active */
+#define TRIG2_ERROR               (1<<5)  /* Trigger 2 Error */
+#define TRIG2_ACTIVE              (1<<4)  /* Trigger 2 Active */
+#define TRIG1_ERROR               (1<<3)  /* Trigger 1 Error */
+#define TRIG1_ACTIVE              (1<<2)  /* Trigger 1 Active */
+#define TRIG0_ERROR               (1<<1)  /* Trigger 0 Error */
+#define TRIG0_ACTIVE              (1<<0)  /* Trigger 0 Active */
+
+/* Bit definitions for the PTP_RATEH register */
+#define PTP_RATE_DIR              (1<<15) /* PTP Rate Direction */
+#define PTP_TMP_RATE              (1<<14) /* PTP Temporary Rate */
+#define PTP_RATE_HI_SHIFT         (0)     /* PTP Rate High 10-bits */
+#define PTP_RATE_HI_MASK          (0x3ff)
+
+/* Bit definitions for the PTP_ESTS register */
+#define EVNTS_MISSED_SHIFT        (8)     /* Indicates number of events missed */
+#define EVNTS_MISSED_MASK         (0x7)
+#define EVNT_TS_LEN_SHIFT         (6)     /* Indicates length of the Timestamp field in 16-bit words minus 1 */
+#define EVNT_TS_LEN_MASK          (0x3)
+#define EVNT_RF                   (1<<5)  /* Indicates whether the event is a rise or falling event */
+#define EVNT_NUM_SHIFT            (2)     /* Indicates Event Timestamp Unit which detected an event */
+#define EVNT_NUM_MASK             (0x7)
+#define MULT_EVNT                 (1<<1)  /* Indicates multiple events were detected at the same time */
+#define EVENT_DET                 (1<<0)  /* PTP Event Detected */
+
+/* Bit definitions for the PTP_EDATA register */
+#define E7_RISE                   (1<<15) /* Indicates direction of Event 7 */
+#define E7_DET                    (1<<14) /* Indicates Event 7 detected */
+#define E6_RISE                   (1<<13) /* Indicates direction of Event 6 */
+#define E6_DET                    (1<<12) /* Indicates Event 6 detected */
+#define E5_RISE                   (1<<11) /* Indicates direction of Event 5 */
+#define E5_DET                    (1<<10) /* Indicates Event 5 detected */
+#define E4_RISE                   (1<<9)  /* Indicates direction of Event 4 */
+#define E4_DET                    (1<<8)  /* Indicates Event 4 detected */
+#define E3_RISE                   (1<<7)  /* Indicates direction of Event 3 */
+#define E3_DET                    (1<<6)  /* Indicates Event 3 detected */
+#define E2_RISE                   (1<<5)  /* Indicates direction of Event 2 */
+#define E2_DET                    (1<<4)  /* Indicates Event 2 detected */
+#define E1_RISE                   (1<<3)  /* Indicates direction of Event 1 */
+#define E1_DET                    (1<<2)  /* Indicates Event 1 detected */
+#define E0_RISE                   (1<<1)  /* Indicates direction of Event 0 */
+#define E0_DET                    (1<<0)  /* Indicates Event 0 detected */
+
+/* Bit definitions for the PTP_TRIG register */
+#define TRIG_PULSE                (1<<15) /* generate a Pulse rather than a single edge */
+#define TRIG_PER                  (1<<14) /* generate a periodic signal */
+#define TRIG_IF_LATE              (1<<13) /* trigger immediately if already past */
+#define TRIG_NOTIFY               (1<<12) /* Trigger Notification Enable */
+#define TRIG_GPIO_SHIFT           (8)     /* Trigger GPIO Connection, value 1-12 */
+#define TRIG_GPIO_MASK            (0xf)
+#define TRIG_TOGGLE               (1<<7)  /* Trigger Toggle Mode Enable */
+#define TRIG_CSEL_SHIFT           (1)     /* Trigger Configuration Select */
+#define TRIG_CSEL_MASK            (0x7)
+#define TRIG_WR                   (1<<0)  /* Trigger Configuration Write */
+
+/* Bit definitions for the PTP_EVNT register */
+#define EVNT_RISE                 (1<<14) /* Event Rise Detect Enable */
+#define EVNT_FALL                 (1<<13) /* Event Fall Detect Enable */
+#define EVNT_SINGLE               (1<<12) /* enable single event capture operation */
+#define EVNT_GPIO_SHIFT           (8)     /* Event GPIO Connection, value 1-12 */
+#define EVNT_GPIO_MASK            (0xf)
+#define EVNT_SEL_SHIFT            (1)     /* Event Select */
+#define EVNT_SEL_MASK             (0x7)
+#define EVNT_WR                   (1<<0)  /* Event Configuration Write */
+
+/* Bit definitions for the PTP_TXCFG0 register */
+#define SYNC_1STEP                (1<<15) /* insert timestamp into transmit Sync Messages */
+#define DR_INSERT                 (1<<13) /* Insert Delay_Req Timestamp in Delay_Resp (dangerous) */
+#define NTP_TS_EN                 (1<<12) /* Enable Timestamping of NTP Packets */
+#define IGNORE_2STEP              (1<<11) /* Ignore Two_Step flag for One-Step operation */
+#define CRC_1STEP                 (1<<10) /* Disable checking of CRC for One-Step operation */
+#define CHK_1STEP                 (1<<9)  /* Enable UDP Checksum correction for One-Step Operation */
+#define IP1588_EN                 (1<<8)  /* Enable IEEE 1588 defined IP address filter */
+#define TX_L2_EN                  (1<<7)  /* Layer2 Timestamp Enable */
+#define TX_IPV6_EN                (1<<6)  /* IPv6 Timestamp Enable */
+#define TX_IPV4_EN                (1<<5)  /* IPv4 Timestamp Enable */
+#define TX_PTP_VER_SHIFT          (1)     /* Enable Timestamp capture for IEEE 1588 version X */
+#define TX_PTP_VER_MASK           (0xf)
+#define TX_TS_EN                  (1<<0)  /* Transmit Timestamp Enable */
+
+/* Bit definitions for the PTP_TXCFG1 register */
+#define BYTE0_MASK_SHIFT          (8)     /* Bit mask to be used for matching Byte0 of the PTP Message */
+#define BYTE0_MASK_MASK           (0xff)
+#define BYTE0_DATA_SHIFT          (0)     /* Data to be used for matching Byte0 of the PTP Message */
+#define BYTE0_DATA_MASK           (0xff)
+
+/* Bit definitions for the PSF_CFG0 register */
+#define MAC_SRC_ADD_SHIFT         (11)    /* Status Frame Mac Source Address */
+#define MAC_SRC_ADD_MASK          (0x3)
+#define MIN_PRE_SHIFT             (8)     /* Status Frame Minimum Preamble */
+#define MIN_PRE_MASK              (0x7)
+#define PSF_ENDIAN                (1<<7)  /* Status Frame Endian Control */
+#define PSF_IPV4                  (1<<6)  /* Status Frame IPv4 Enable */
+#define PSF_PCF_RD                (1<<5)  /* Control Frame Read PHY Status Frame Enable */
+#define PSF_ERR_EN                (1<<4)  /* Error PHY Status Frame Enable */
+#define PSF_TXTS_EN               (1<<3)  /* Transmit Timestamp PHY Status Frame Enable */
+#define PSF_RXTS_EN               (1<<2)  /* Receive Timestamp PHY Status Frame Enable */
+#define PSF_TRIG_EN               (1<<1)  /* Trigger PHY Status Frame Enable */
+#define PSF_EVNT_EN               (1<<0)  /* Event PHY Status Frame Enable */
+
+/* Bit definitions for the PTP_RXCFG0 register */
+#define DOMAIN_EN                 (1<<15) /* Domain Match Enable */
+#define ALT_MAST_DIS              (1<<14) /* Alternate Master Timestamp Disable */
+#define USER_IP_SEL               (1<<13) /* Selects portion of IP address accessible thru PTP_RXCFG2 */
+#define USER_IP_EN                (1<<12) /* Enable User-programmed IP address filter */
+#define RX_SLAVE                  (1<<11) /* Receive Slave Only */
+#define IP1588_EN_SHIFT           (8)     /* Enable IEEE 1588 defined IP address filters */
+#define IP1588_EN_MASK            (0xf)
+#define RX_L2_EN                  (1<<7)  /* Layer2 Timestamp Enable */
+#define RX_IPV6_EN                (1<<6)  /* IPv6 Timestamp Enable */
+#define RX_IPV4_EN                (1<<5)  /* IPv4 Timestamp Enable */
+#define RX_PTP_VER_SHIFT          (1)     /* Enable Timestamp capture for IEEE 1588 version X */
+#define RX_PTP_VER_MASK           (0xf)
+#define RX_TS_EN                  (1<<0)  /* Receive Timestamp Enable */
+
+/* Bit definitions for the PTP_RXCFG1 register */
+#define BYTE0_MASK_SHIFT          (8)     /* Bit mask to be used for matching Byte0 of the PTP Message */
+#define BYTE0_MASK_MASK           (0xff)
+#define BYTE0_DATA_SHIFT          (0)     /* Data to be used for matching Byte0 of the PTP Message */
+#define BYTE0_DATA_MASK           (0xff)
+
+/* Bit definitions for the PTP_RXCFG3 register */
+#define TS_MIN_IFG_SHIFT          (12)    /* Minimum Inter-frame Gap */
+#define TS_MIN_IFG_MASK           (0xf)
+#define ACC_UDP                   (1<<11) /* Record Timestamp if UDP Checksum Error */
+#define ACC_CRC                   (1<<10) /* Record Timestamp if CRC Error */
+#define TS_APPEND                 (1<<9)  /* Append Timestamp for L2 */
+#define TS_INSERT                 (1<<8)  /* Enable Timestamp Insertion */
+#define PTP_DOMAIN_SHIFT          (0)     /* PTP Message domainNumber field */
+#define PTP_DOMAIN_MASK           (0xff)
+
+/* Bit definitions for the PTP_RXCFG4 register */
+#define IPV4_UDP_MOD              (1<<15) /* Enable IPV4 UDP Modification */
+#define TS_SEC_EN                 (1<<14) /* Enable Timestamp Seconds */
+#define TS_SEC_LEN_SHIFT          (12)    /* Inserted Timestamp Seconds Length */
+#define TS_SEC_LEN_MASK           (0x3)
+#define RXTS_NS_OFF_SHIFT         (6)     /* Receive Timestamp Nanoseconds offset */
+#define RXTS_NS_OFF_MASK          (0x3f)
+#define RXTS_SEC_OFF_SHIFT        (0)     /* Receive Timestamp Seconds offset */
+#define RXTS_SEC_OFF_MASK         (0x3f)
+
+/* Bit definitions for the PTP_COC register */
+#define PTP_CLKOUT_EN             (1<<15) /* PTP Clock Output Enable */
+#define PTP_CLKOUT_SEL            (1<<14) /* PTP Clock Output Source Select */
+#define PTP_CLKOUT_SPEEDSEL       (1<<13) /* PTP Clock Output I/O Speed Select */
+#define PTP_CLKDIV_SHIFT          (0)     /* PTP Clock Divide-by Value */
+#define PTP_CLKDIV_MASK           (0xff)
+
+/* Bit definitions for the PSF_CFG1 register */
+#define PTPRESERVED_SHIFT         (12)    /* PTP v2 reserved field */
+#define PTPRESERVED_MASK          (0xf)
+#define VERSIONPTP_SHIFT          (8)     /* PTP v2 versionPTP field */
+#define VERSIONPTP_MASK           (0xf)
+#define TRANSPORT_SPECIFIC_SHIFT  (4)     /* PTP v2 Header transportSpecific field */
+#define TRANSPORT_SPECIFIC_MASK   (0xf)
+#define MESSAGETYPE_SHIFT         (0)     /* PTP v2 messageType field */
+#define MESSAGETYPE_MASK          (0xf)
+
+/* Bit definitions for the PTP_SFDCFG register */
+#define TX_SFD_GPIO_SHIFT         (4)     /* TX SFD GPIO Select, value 1-12 */
+#define TX_SFD_GPIO_MASK          (0xf)
+#define RX_SFD_GPIO_SHIFT         (0)     /* RX SFD GPIO Select, value 1-12 */
+#define RX_SFD_GPIO_MASK          (0xf)
+
+/* Bit definitions for the PTP_INTCTL register */
+#define PTP_INT_GPIO_SHIFT        (0)     /* PTP Interrupt GPIO Select */
+#define PTP_INT_GPIO_MASK         (0xf)
+
+/* Bit definitions for the PTP_CLKSRC register */
+#define CLK_SRC_SHIFT             (14)    /* PTP Clock Source Select */
+#define CLK_SRC_MASK              (0x3)
+#define CLK_SRC_PER_SHIFT         (0)     /* PTP Clock Source Period */
+#define CLK_SRC_PER_MASK          (0x7f)
+
+/* Bit definitions for the PTP_OFF register */
+#define PTP_OFFSET_SHIFT          (0)     /* PTP Message offset from preceding header */
+#define PTP_OFFSET_MASK           (0xff)
+
+#endif
diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index fcfafd0..68d7201 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -53,4 +53,23 @@ config PTP_1588_CLOCK_IXP46X
 	  To compile this driver as a module, choose M here: the module
 	  will be called ptp_ixp46x.
 
+comment "Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks."
+	depends on PTP_1588_CLOCK && (PHYLIB=n || NETWORK_PHY_TIMESTAMPING=n)
+
+config DP83640_PHY
+	tristate "Driver for the National Semiconductor DP83640 PHYTER"
+	depends on PTP_1588_CLOCK
+	depends on NETWORK_PHY_TIMESTAMPING
+	depends on PHYLIB
+	---help---
+	  Supports the DP83640 PHYTER with IEEE 1588 features.
+
+	  This driver adds support for using the DP83640 as a PTP
+	  clock. This clock is only useful if your PTP programs are
+	  getting hardware time stamps on the PTP Ethernet packets
+	  using the SO_TIMESTAMPING API.
+
+	  In order for this to work, your MAC driver must also
+	  implement the skb_tx_timetamp() function.
+
 endmenu
-- 
1.7.0.4

^ permalink raw reply related

* [PATCH 3/5] powerpc, hw_breakpoints: Fix racy access to ptrace breakpoints
From: Frederic Weisbecker @ 2011-04-22 13:16 UTC (permalink / raw)
  To: LPPC
  Cc: Peter Zijlstra, Frederic Weisbecker, Will Deacon, LKML,
	Oleg Nesterov, Paul Mundt, Ingo Molnar, Prasad, v2.6.33..
In-Reply-To: <1302284067-7860-4-git-send-email-fweisbec@gmail.com>

(resend with ppc list in cc)

While the tracer accesses ptrace breakpoints, the child task may
concurrently exit due to a SIGKILL and thus release its breakpoints
at the same time. We can then dereference some freed pointers.

To fix this, hold a reference on the child breakpoints before
manipulating them.

Reported-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Prasad <prasad@linux.vnet.ibm.com>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: v2.6.33.. <stable@kernel.org>
---
 arch/powerpc/kernel/ptrace.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 55613e3..4edeeb3 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -1591,7 +1591,10 @@ long arch_ptrace(struct task_struct *child, long request,
 	}
 
 	case PTRACE_SET_DEBUGREG:
+		if (ptrace_get_breakpoints(child) < 0)
+			return -ESRCH;
 		ret = ptrace_set_debugreg(child, addr, data);
+		ptrace_put_breakpoints(child);
 		break;
 
 #ifdef CONFIG_PPC64
-- 
1.7.3.2

^ permalink raw reply related

* [PATCH 0/3] powerpc/eeh: Bug fix and enhancement
From: Richard A Lary @ 2011-04-22 19:59 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: antonb

This patch set contains three patches, all to eeh.c,
which fix a issue seen on PCIe adapters with devices below
PCIe bridge/switch, gracefully handle case where driver
sets 'needs_freset' for non-PCIe adapter, and display
location information for both PCIe bus and device for
the device which detected an error.

Patches were tested on P5/P6/P7 platforms on a variety
of PCI, PCI-X and PCI-E adapters with no regressions.

^ permalink raw reply

* [PATCH 1/3]  [PATCH 1/3]powerpc/eeh: Propagate needs_freset flag to device at PE
From: Richard A Lary @ 2011-04-22 19:59 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: antonb

From: Richard A Lary <rlary@linux.vnet.ibm.com>

  For multifunction adapters with a PCI bridge or switch as the device
  at the Partitionable Endpoint(PE), if one or more devices below PE
  sets dev->needs_freset, that value will be set for the PE device.

  In other words, if any device below PE requires a fundamental reset
  the PE will request a fundamental reset.

Signed-off-by: Richard A Lary <rlary@linux.vnet.ibm.com>
---
  arch/powerpc/platforms/pseries/eeh.c |   48 	42 +	6 -	0 !
  1 file changed, 42 insertions(+), 6 deletions(-)

Index: b/arch/powerpc/platforms/pseries/eeh.c
===================================================================
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -448,6 +448,39 @@ void eeh_clear_slot (struct device_node
  	raw_spin_unlock_irqrestore(&confirm_error_lock, flags);
  }

+void __eeh_set_pe_freset(struct device_node *parent, unsigned int *freset)
+{
+	struct device_node *dn;
+
+	for_each_child_of_node(parent, dn) {
+		if (PCI_DN(dn)) {
+
+			struct pci_dev *dev = PCI_DN(dn)->pcidev;
+
+			if (dev && dev->driver)
+				*freset |= dev->needs_freset;
+
+			__eeh_set_pe_freset(dn, freset);
+		}
+	}
+}
+
+void eeh_set_pe_freset(struct device_node *dn, unsigned int *freset)
+{
+	struct pci_dev *dev;
+	dn = find_device_pe(dn);
+
+	/* Back up one, since config addrs might be shared */
+	if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent))
+		dn = dn->parent;
+
+	dev = PCI_DN(dn)->pcidev;
+	if (dev)
+		*freset |= dev->needs_freset;
+
+	__eeh_set_pe_freset(dn, freset);
+}
+
  /**
   * eeh_dn_check_failure - check if all 1's data is due to EEH slot freeze
   * @dn device node
@@ -736,18 +769,21 @@ int pcibios_set_pcie_reset_state(struct
  /**
   * rtas_set_slot_reset -- assert the pci #RST line for 1/4 second
   * @pdn: pci device node to be reset.
- *
- *  Return 0 if success, else a non-zero value.
   */

  static void __rtas_set_slot_reset(struct pci_dn *pdn)
  {
-	struct pci_dev *dev = pdn->pcidev;
+	unsigned int freset = 0;

-	/* Determine type of EEH reset required by device,
-	 * default hot reset or fundamental reset
+	/* Determine type of EEH reset required for
+	 * Partitionable Endpoint, a hot-reset (1)
+	 * or a fundamental reset (3).
+	 * A fundamental reset required by any device under
+	 * Partitionable Endpoint trumps hot-reset.
  	 */
-	if (dev && dev->needs_freset)
+	eeh_set_pe_freset(pdn->node, &freset);
+
+	if (freset)
  		rtas_pci_slot_reset(pdn, 3);
  	else
  		rtas_pci_slot_reset(pdn, 1);

^ permalink raw reply

* [PATCH 2/3] powerpc/eeh: Handle functional reset on non-PCIe device
From: Richard A Lary @ 2011-04-22 20:00 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: antonb

From: Richard A Lary <rlary@linux.vnet.ibm.com>

  Fundamental reset is an optional reset type supported only by PCIe adapters.
  Handle the unexpected case where a non-PCIe device has requested a
  fundamental reset. Try hot-reset as a fallback to handle this case.

Signed-off-by: Richard A Lary <rlary@linux.vnet.ibm.com>
---
  arch/powerpc/platforms/pseries/eeh.c |   21 	16 +	5 -	0 !
  1 file changed, 16 insertions(+), 5 deletions(-)

Index: b/arch/powerpc/platforms/pseries/eeh.c
===================================================================
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -725,15 +725,26 @@ rtas_pci_slot_reset(struct pci_dn *pdn,
  	if (pdn->eeh_pe_config_addr)
  		config_addr = pdn->eeh_pe_config_addr;

-	rc = rtas_call(ibm_set_slot_reset,4,1, NULL,
+	rc = rtas_call(ibm_set_slot_reset, 4, 1, NULL,
  	               config_addr,
  	               BUID_HI(pdn->phb->buid),
  	               BUID_LO(pdn->phb->buid),
  	               state);
-	if (rc)
-		printk (KERN_WARNING "EEH: Unable to reset the failed slot,"
-		        " (%d) #RST=%d dn=%s\n",
-		        rc, state, pdn->node->full_name);
+
+	/* Fundamental-reset not supported on this PE, try hot-reset */
+	if (rc == -8 && state == 3) {
+		state = 1;
+		rc = rtas_call(ibm_set_slot_reset, 4, 1, NULL,
+			       config_addr,
+			       BUID_HI(pdn->phb->buid),
+			       BUID_LO(pdn->phb->buid),
+			       state);
+		if (rc)
+			printk(KERN_WARNING
+				"EEH: Unable to reset the failed slot,"
+				" (%d) #RST=%d dn=%s\n",
+				rc, state, pdn->node->full_name);
+	}
  }

  /**

^ permalink raw reply

* [PATCH 3/3] powerpc/eeh: Handle functional reset on non-PCIe device
From: Richard A Lary @ 2011-04-22 20:00 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: antonb

From: Richard A Lary <rlary@linux.vnet.ibm.com>

  For adapters which have devices under a PCIe switch/bridge it is informative
  to display information for both the PCIe switch/bridge and the device on
  which the bus error was detected.

Signed-off-by: Richard A Lary <rlary@linux.vnet.ibm.com>
---
  arch/powerpc/platforms/pseries/eeh_driver.c |   24 	14 +	10 -	0 !
  1 file changed, 14 insertions(+), 10 deletions(-)

Index: b/arch/powerpc/platforms/pseries/eeh_driver.c
===================================================================
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -328,7 +328,7 @@ struct pci_dn * handle_eeh_events (struc
  	struct pci_bus *frozen_bus;
  	int rc = 0;
  	enum pci_ers_result result = PCI_ERS_RESULT_NONE;
-	const char *location, *pci_str, *drv_str;
+	const char *location, *pci_str, *drv_str, *bus_pci_str, *bus_drv_str;

  	frozen_dn = find_device_pe(event->dn);
  	if (!frozen_dn) {
@@ -364,22 +364,26 @@ struct pci_dn * handle_eeh_events (struc
  	frozen_pdn = PCI_DN(frozen_dn);
  	frozen_pdn->eeh_freeze_count++;

-	if (frozen_pdn->pcidev) {
-		pci_str = pci_name (frozen_pdn->pcidev);
-		drv_str = pcid_name (frozen_pdn->pcidev);
-	} else {
-		pci_str = eeh_pci_name(event->dev);
-		drv_str = pcid_name (event->dev);
-	}
-	
+	pci_str = eeh_pci_name(event->dev);
+	drv_str = pcid_name(event->dev);
+
  	if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES)
  		goto excess_failures;

  	printk(KERN_WARNING
  	   "EEH: This PCI device has failed %d times in the last hour:\n",
  		frozen_pdn->eeh_freeze_count);
+
+	if (frozen_pdn->pcidev) {
+		bus_pci_str = pci_name(frozen_pdn->pcidev);
+		bus_drv_str = pcid_name(frozen_pdn->pcidev);
+		printk(KERN_WARNING
+			"EEH: Bus location=%s driver=%s pci addr=%s\n",
+			location, bus_drv_str, bus_pci_str);
+	}
+
  	printk(KERN_WARNING
-		"EEH: location=%s driver=%s pci addr=%s\n",
+		"EEH: Device location=%s driver=%s pci addr=%s\n",
  		location, drv_str, pci_str);

  	/* Walk the various device drivers attached to this slot through

^ permalink raw reply

* [PATCH 3/3] powerpc/eeh: Display eeh error location for bus and device (resend)
From: Richard A Lary @ 2011-04-22 20:08 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: antonb

From: Richard A Lary <rlary@linux.vnet.ibm.com>

  For adapters which have devices under a PCIe switch/bridge it is informative
  to display information for both the PCIe switch/bridge and the device on
  which the bus error was detected.

Signed-off-by: Richard A Lary <rlary@linux.vnet.ibm.com>
---
  arch/powerpc/platforms/pseries/eeh_driver.c |   24 	14 +	10 -	0 !
  1 file changed, 14 insertions(+), 10 deletions(-)

Index: b/arch/powerpc/platforms/pseries/eeh_driver.c
===================================================================
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -328,7 +328,7 @@ struct pci_dn * handle_eeh_events (struc
  	struct pci_bus *frozen_bus;
  	int rc = 0;
  	enum pci_ers_result result = PCI_ERS_RESULT_NONE;
-	const char *location, *pci_str, *drv_str;
+	const char *location, *pci_str, *drv_str, *bus_pci_str, *bus_drv_str;

  	frozen_dn = find_device_pe(event->dn);
  	if (!frozen_dn) {
@@ -364,22 +364,26 @@ struct pci_dn * handle_eeh_events (struc
  	frozen_pdn = PCI_DN(frozen_dn);
  	frozen_pdn->eeh_freeze_count++;

-	if (frozen_pdn->pcidev) {
-		pci_str = pci_name (frozen_pdn->pcidev);
-		drv_str = pcid_name (frozen_pdn->pcidev);
-	} else {
-		pci_str = eeh_pci_name(event->dev);
-		drv_str = pcid_name (event->dev);
-	}
-	
+	pci_str = eeh_pci_name(event->dev);
+	drv_str = pcid_name(event->dev);
+
  	if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES)
  		goto excess_failures;

  	printk(KERN_WARNING
  	   "EEH: This PCI device has failed %d times in the last hour:\n",
  		frozen_pdn->eeh_freeze_count);
+
+	if (frozen_pdn->pcidev) {
+		bus_pci_str = pci_name(frozen_pdn->pcidev);
+		bus_drv_str = pcid_name(frozen_pdn->pcidev);
+		printk(KERN_WARNING
+			"EEH: Bus location=%s driver=%s pci addr=%s\n",
+			location, bus_drv_str, bus_pci_str);
+	}
+
  	printk(KERN_WARNING
-		"EEH: location=%s driver=%s pci addr=%s\n",
+		"EEH: Device location=%s driver=%s pci addr=%s\n",
  		location, drv_str, pci_str);

  	/* Walk the various device drivers attached to this slot through

^ permalink raw reply

* [PATCH 1/1] powerpc: Add page coalescing support
From: Brian King @ 2011-04-22 21:08 UTC (permalink / raw)
  To: benh; +Cc: brking, linuxppc-dev


Adds support for page coalescing, which is a feature on IBM Power servers
which allows for coalescing identical pages between logical partitions.
Hint text pages as coalesce candidates, since they are the most likely
pages to be able to be coalesced between partitions. This patch also
exports some page coalescing statistics available from firmware via
lparcfg.

Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
---

 arch/powerpc/include/asm/firmware.h         |    3 +-
 arch/powerpc/include/asm/hvcall.h           |   12 ++++++++
 arch/powerpc/include/asm/pSeries_reconfig.h |    6 ++++
 arch/powerpc/kernel/lparcfg.c               |   40 ++++++++++++++++++++++++++++
 arch/powerpc/kernel/prom_init.c             |    4 ++
 arch/powerpc/kernel/rtas.c                  |    2 +
 arch/powerpc/platforms/pseries/lpar.c       |    2 +
 arch/powerpc/platforms/pseries/setup.c      |   11 +++++++
 8 files changed, 78 insertions(+), 2 deletions(-)

diff -puN arch/powerpc/include/asm/hvcall.h~powerpc_coalesce arch/powerpc/include/asm/hvcall.h
--- linux-2.6/arch/powerpc/include/asm/hvcall.h~powerpc_coalesce	2011-04-20 08:38:42.000000000 -0500
+++ linux-2.6-bjking1/arch/powerpc/include/asm/hvcall.h	2011-04-20 08:38:42.000000000 -0500
@@ -102,6 +102,7 @@
 #define H_ANDCOND		(1UL<<(63-33))
 #define H_ICACHE_INVALIDATE	(1UL<<(63-40))	/* icbi, etc.  (ignored for IO pages) */
 #define H_ICACHE_SYNCHRONIZE	(1UL<<(63-41))	/* dcbst, icbi, etc (ignored for IO pages */
+#define H_COALESCE_CAND	(1UL<<(63-42))	/* page is a good candidate for coalescing */
 #define H_ZERO_PAGE		(1UL<<(63-48))	/* zero the page before mapping (ignored for IO pages) */
 #define H_COPY_PAGE		(1UL<<(63-49))
 #define H_N			(1UL<<(63-61))
@@ -234,6 +235,7 @@
 #define H_GET_MPP		0x2D4
 #define H_HOME_NODE_ASSOCIATIVITY 0x2EC
 #define H_BEST_ENERGY		0x2F4
+#define H_GET_MPP_X		0x314
 #define MAX_HCALL_OPCODE	H_BEST_ENERGY
 
 #ifndef __ASSEMBLY__
@@ -312,6 +314,16 @@ struct hvcall_mpp_data {
 
 int h_get_mpp(struct hvcall_mpp_data *);
 
+struct hvcall_mpp_x_data {
+	unsigned long coalesced_bytes;
+	unsigned long pool_coalesced_bytes;
+	unsigned long pool_purr_cycles;
+	unsigned long pool_spurr_cycles;
+	unsigned long reserved[3];
+};
+
+int h_get_mpp_x(struct hvcall_mpp_x_data *mpp_x_data);
+
 #ifdef CONFIG_PPC_PSERIES
 extern int CMO_PrPSP;
 extern int CMO_SecPSP;
diff -puN arch/powerpc/platforms/pseries/setup.c~powerpc_coalesce arch/powerpc/platforms/pseries/setup.c
--- linux-2.6/arch/powerpc/platforms/pseries/setup.c~powerpc_coalesce	2011-04-20 08:38:42.000000000 -0500
+++ linux-2.6-bjking1/arch/powerpc/platforms/pseries/setup.c	2011-04-20 08:38:42.000000000 -0500
@@ -403,6 +403,16 @@ static int pseries_set_xdabr(unsigned lo
 #define CMO_CHARACTERISTICS_TOKEN 44
 #define CMO_MAXLENGTH 1026
 
+void pSeries_coalesce_init(void)
+{
+	struct hvcall_mpp_x_data mpp_x_data;
+
+	if (firmware_has_feature(FW_FEATURE_CMO) && !h_get_mpp_x(&mpp_x_data))
+		powerpc_firmware_features |= FW_FEATURE_XCMO;
+	else
+		powerpc_firmware_features &= ~FW_FEATURE_XCMO;
+}
+
 /**
  * fw_cmo_feature_init - FW_FEATURE_CMO is not stored in ibm,hypertas-functions,
  * handle that here. (Stolen from parse_system_parameter_string)
@@ -472,6 +482,7 @@ void pSeries_cmo_feature_init(void)
 		pr_debug("CMO enabled, PrPSP=%d, SecPSP=%d\n", CMO_PrPSP,
 		         CMO_SecPSP);
 		powerpc_firmware_features |= FW_FEATURE_CMO;
+		pSeries_coalesce_init();
 	} else
 		pr_debug("CMO not enabled, PrPSP=%d, SecPSP=%d\n", CMO_PrPSP,
 		         CMO_SecPSP);
diff -puN arch/powerpc/kernel/prom_init.c~powerpc_coalesce arch/powerpc/kernel/prom_init.c
--- linux-2.6/arch/powerpc/kernel/prom_init.c~powerpc_coalesce	2011-04-20 08:38:42.000000000 -0500
+++ linux-2.6-bjking1/arch/powerpc/kernel/prom_init.c	2011-04-20 08:38:42.000000000 -0500
@@ -676,8 +676,10 @@ static void __init early_cmdline_parse(v
 #endif /* CONFIG_PCI_MSI */
 #ifdef CONFIG_PPC_SMLPAR
 #define OV5_CMO			0x80	/* Cooperative Memory Overcommitment */
+#define OV5_XCMO			0x40	/* Page Coalescing */
 #else
 #define OV5_CMO			0x00
+#define OV5_XCMO			0x00
 #endif
 #define OV5_TYPE1_AFFINITY	0x80	/* Type 1 NUMA affinity */
 
@@ -732,7 +734,7 @@ static unsigned char ibm_architecture_ve
 	OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY |
 	OV5_DONATE_DEDICATE_CPU | OV5_MSI,
 	0,
-	OV5_CMO,
+	OV5_CMO | OV5_XCMO,
 	OV5_TYPE1_AFFINITY,
 	0,
 	0,
diff -puN arch/powerpc/kernel/lparcfg.c~powerpc_coalesce arch/powerpc/kernel/lparcfg.c
--- linux-2.6/arch/powerpc/kernel/lparcfg.c~powerpc_coalesce	2011-04-20 08:38:42.000000000 -0500
+++ linux-2.6-bjking1/arch/powerpc/kernel/lparcfg.c	2011-04-20 08:38:42.000000000 -0500
@@ -161,6 +161,21 @@ int h_get_mpp(struct hvcall_mpp_data *mp
 }
 EXPORT_SYMBOL(h_get_mpp);
 
+int h_get_mpp_x(struct hvcall_mpp_x_data *mpp_x_data)
+{
+	int rc;
+	unsigned long retbuf[PLPAR_HCALL9_BUFSIZE] = { 0 };
+
+	rc = plpar_hcall9(H_GET_MPP_X, retbuf);
+
+	mpp_x_data->coalesced_bytes = retbuf[0];
+	mpp_x_data->pool_coalesced_bytes = retbuf[1];
+	mpp_x_data->pool_purr_cycles = retbuf[2];
+	mpp_x_data->pool_spurr_cycles = retbuf[3];
+
+	return rc;
+}
+
 struct hvcall_ppp_data {
 	u64	entitlement;
 	u64	unallocated_entitlement;
@@ -345,6 +360,30 @@ static void parse_mpp_data(struct seq_fi
 	seq_printf(m, "backing_memory=%ld bytes\n", mpp_data.backing_mem);
 }
 
+/**
+ * parse_mpp_x_data
+ * Parse out data returned from h_get_mpp_x
+ */
+static void parse_mpp_x_data(struct seq_file *m)
+{
+	struct hvcall_mpp_x_data mpp_x_data;
+
+	if (!firmware_has_feature(FW_FEATURE_XCMO))
+		return;
+	if (h_get_mpp_x(&mpp_x_data))
+		return;
+
+	seq_printf(m, "coalesced_bytes=%ld\n", mpp_x_data.coalesced_bytes);
+
+	if (mpp_x_data.pool_coalesced_bytes)
+		seq_printf(m, "pool_coalesced_bytes=%ld\n",
+			   mpp_x_data.pool_coalesced_bytes);
+	if (mpp_x_data.pool_purr_cycles)
+		seq_printf(m, "coalesce_pool_purr=%ld\n", mpp_x_data.pool_purr_cycles);
+	if (mpp_x_data.pool_spurr_cycles)
+		seq_printf(m, "coalesce_pool_spurr=%ld\n", mpp_x_data.pool_spurr_cycles);
+}
+
 #define SPLPAR_CHARACTERISTICS_TOKEN 20
 #define SPLPAR_MAXLENGTH 1026*(sizeof(char))
 
@@ -520,6 +559,7 @@ static int pseries_lparcfg_data(struct s
 		parse_system_parameter_string(m);
 		parse_ppp_data(m);
 		parse_mpp_data(m);
+		parse_mpp_x_data(m);
 		pseries_cmo_data(m);
 		splpar_dispatch_data(m);
 
diff -puN arch/powerpc/include/asm/firmware.h~powerpc_coalesce arch/powerpc/include/asm/firmware.h
--- linux-2.6/arch/powerpc/include/asm/firmware.h~powerpc_coalesce	2011-04-20 08:38:42.000000000 -0500
+++ linux-2.6-bjking1/arch/powerpc/include/asm/firmware.h	2011-04-20 08:38:42.000000000 -0500
@@ -47,6 +47,7 @@
 #define FW_FEATURE_BEAT		ASM_CONST(0x0000000001000000)
 #define FW_FEATURE_CMO		ASM_CONST(0x0000000002000000)
 #define FW_FEATURE_VPHN		ASM_CONST(0x0000000004000000)
+#define FW_FEATURE_XCMO		ASM_CONST(0x0000000008000000)
 
 #ifndef __ASSEMBLY__
 
@@ -60,7 +61,7 @@ enum {
 		FW_FEATURE_VIO | FW_FEATURE_RDMA | FW_FEATURE_LLAN |
 		FW_FEATURE_BULK_REMOVE | FW_FEATURE_XDABR |
 		FW_FEATURE_MULTITCE | FW_FEATURE_SPLPAR | FW_FEATURE_LPAR |
-		FW_FEATURE_CMO | FW_FEATURE_VPHN,
+		FW_FEATURE_CMO | FW_FEATURE_VPHN | FW_FEATURE_XCMO,
 	FW_FEATURE_PSERIES_ALWAYS = 0,
 	FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
 	FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
diff -puN arch/powerpc/platforms/pseries/lpar.c~powerpc_coalesce arch/powerpc/platforms/pseries/lpar.c
--- linux-2.6/arch/powerpc/platforms/pseries/lpar.c~powerpc_coalesce	2011-04-20 08:38:42.000000000 -0500
+++ linux-2.6-bjking1/arch/powerpc/platforms/pseries/lpar.c	2011-04-20 08:38:42.000000000 -0500
@@ -329,6 +329,8 @@ static long pSeries_lpar_hpte_insert(uns
 	/* Make pHyp happy */
 	if ((rflags & _PAGE_NO_CACHE) & !(rflags & _PAGE_WRITETHRU))
 		hpte_r &= ~_PAGE_COHERENT;
+	if (firmware_has_feature(FW_FEATURE_XCMO) && !(hpte_r & HPTE_R_N))
+		flags |= H_COALESCE_CAND;
 
 	lpar_rc = plpar_pte_enter(flags, hpte_group, hpte_v, hpte_r, &slot);
 	if (unlikely(lpar_rc == H_PTEG_FULL)) {
diff -puN arch/powerpc/include/asm/pSeries_reconfig.h~powerpc_coalesce arch/powerpc/include/asm/pSeries_reconfig.h
--- linux-2.6/arch/powerpc/include/asm/pSeries_reconfig.h~powerpc_coalesce	2011-04-20 08:38:42.000000000 -0500
+++ linux-2.6-bjking1/arch/powerpc/include/asm/pSeries_reconfig.h	2011-04-20 08:38:42.000000000 -0500
@@ -14,6 +14,12 @@
 #define PSERIES_DRCONF_MEM_ADD		0x0003
 #define PSERIES_DRCONF_MEM_REMOVE	0x0004
 
+#ifdef CONFIG_PPC_SMLPAR
+extern void pSeries_coalesce_init(void);
+#else
+static inline void pSeries_coalesce_init(void) { }
+#endif
+
 #ifdef CONFIG_PPC_PSERIES
 extern int pSeries_reconfig_notifier_register(struct notifier_block *);
 extern void pSeries_reconfig_notifier_unregister(struct notifier_block *);
diff -puN arch/powerpc/kernel/rtas.c~powerpc_coalesce arch/powerpc/kernel/rtas.c
--- linux-2.6/arch/powerpc/kernel/rtas.c~powerpc_coalesce	2011-04-20 08:38:42.000000000 -0500
+++ linux-2.6-bjking1/arch/powerpc/kernel/rtas.c	2011-04-20 08:38:42.000000000 -0500
@@ -42,6 +42,7 @@
 #include <asm/time.h>
 #include <asm/mmu.h>
 #include <asm/topology.h>
+#include <asm/pSeries_reconfig.h>
 
 struct rtas_t rtas = {
 	.lock = __ARCH_SPIN_LOCK_UNLOCKED
@@ -731,6 +732,7 @@ static int __rtas_suspend_last_cpu(struc
 
 	atomic_set(&data->error, rc);
 	start_topology_update();
+	pSeries_coalesce_init();
 
 	if (wake_when_done) {
 		atomic_set(&data->done, 1);
_

^ permalink raw reply

* Re: [PATCH 1/1] powerpc: Add page coalescing support
From: Benjamin Herrenschmidt @ 2011-04-22 22:59 UTC (permalink / raw)
  To: Brian King; +Cc: linuxppc-dev
In-Reply-To: <201104222108.p3ML8WQt002094@d03av05.boulder.ibm.com>

On Fri, 2011-04-22 at 16:08 -0500, Brian King wrote:
> Adds support for page coalescing, which is a feature on IBM Power servers
> which allows for coalescing identical pages between logical partitions.
> Hint text pages as coalesce candidates, since they are the most likely
> pages to be able to be coalesced between partitions. This patch also
> exports some page coalescing statistics available from firmware via
> lparcfg.

Hi Brian !

Is this patch different from the version you posted previously which is
already on Patchwork ? I'm in the process of putting together
powerpc-next and your previous variant is in my queue.

Cheers,
Ben.
 
> Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
> ---
> 
>  arch/powerpc/include/asm/firmware.h         |    3 +-
>  arch/powerpc/include/asm/hvcall.h           |   12 ++++++++
>  arch/powerpc/include/asm/pSeries_reconfig.h |    6 ++++
>  arch/powerpc/kernel/lparcfg.c               |   40 ++++++++++++++++++++++++++++
>  arch/powerpc/kernel/prom_init.c             |    4 ++
>  arch/powerpc/kernel/rtas.c                  |    2 +
>  arch/powerpc/platforms/pseries/lpar.c       |    2 +
>  arch/powerpc/platforms/pseries/setup.c      |   11 +++++++
>  8 files changed, 78 insertions(+), 2 deletions(-)
> 
> diff -puN arch/powerpc/include/asm/hvcall.h~powerpc_coalesce arch/powerpc/include/asm/hvcall.h
> --- linux-2.6/arch/powerpc/include/asm/hvcall.h~powerpc_coalesce	2011-04-20 08:38:42.000000000 -0500
> +++ linux-2.6-bjking1/arch/powerpc/include/asm/hvcall.h	2011-04-20 08:38:42.000000000 -0500
> @@ -102,6 +102,7 @@
>  #define H_ANDCOND		(1UL<<(63-33))
>  #define H_ICACHE_INVALIDATE	(1UL<<(63-40))	/* icbi, etc.  (ignored for IO pages) */
>  #define H_ICACHE_SYNCHRONIZE	(1UL<<(63-41))	/* dcbst, icbi, etc (ignored for IO pages */
> +#define H_COALESCE_CAND	(1UL<<(63-42))	/* page is a good candidate for coalescing */
>  #define H_ZERO_PAGE		(1UL<<(63-48))	/* zero the page before mapping (ignored for IO pages) */
>  #define H_COPY_PAGE		(1UL<<(63-49))
>  #define H_N			(1UL<<(63-61))
> @@ -234,6 +235,7 @@
>  #define H_GET_MPP		0x2D4
>  #define H_HOME_NODE_ASSOCIATIVITY 0x2EC
>  #define H_BEST_ENERGY		0x2F4
> +#define H_GET_MPP_X		0x314
>  #define MAX_HCALL_OPCODE	H_BEST_ENERGY
>  
>  #ifndef __ASSEMBLY__
> @@ -312,6 +314,16 @@ struct hvcall_mpp_data {
>  
>  int h_get_mpp(struct hvcall_mpp_data *);
>  
> +struct hvcall_mpp_x_data {
> +	unsigned long coalesced_bytes;
> +	unsigned long pool_coalesced_bytes;
> +	unsigned long pool_purr_cycles;
> +	unsigned long pool_spurr_cycles;
> +	unsigned long reserved[3];
> +};
> +
> +int h_get_mpp_x(struct hvcall_mpp_x_data *mpp_x_data);
> +
>  #ifdef CONFIG_PPC_PSERIES
>  extern int CMO_PrPSP;
>  extern int CMO_SecPSP;
> diff -puN arch/powerpc/platforms/pseries/setup.c~powerpc_coalesce arch/powerpc/platforms/pseries/setup.c
> --- linux-2.6/arch/powerpc/platforms/pseries/setup.c~powerpc_coalesce	2011-04-20 08:38:42.000000000 -0500
> +++ linux-2.6-bjking1/arch/powerpc/platforms/pseries/setup.c	2011-04-20 08:38:42.000000000 -0500
> @@ -403,6 +403,16 @@ static int pseries_set_xdabr(unsigned lo
>  #define CMO_CHARACTERISTICS_TOKEN 44
>  #define CMO_MAXLENGTH 1026
>  
> +void pSeries_coalesce_init(void)
> +{
> +	struct hvcall_mpp_x_data mpp_x_data;
> +
> +	if (firmware_has_feature(FW_FEATURE_CMO) && !h_get_mpp_x(&mpp_x_data))
> +		powerpc_firmware_features |= FW_FEATURE_XCMO;
> +	else
> +		powerpc_firmware_features &= ~FW_FEATURE_XCMO;
> +}
> +
>  /**
>   * fw_cmo_feature_init - FW_FEATURE_CMO is not stored in ibm,hypertas-functions,
>   * handle that here. (Stolen from parse_system_parameter_string)
> @@ -472,6 +482,7 @@ void pSeries_cmo_feature_init(void)
>  		pr_debug("CMO enabled, PrPSP=%d, SecPSP=%d\n", CMO_PrPSP,
>  		         CMO_SecPSP);
>  		powerpc_firmware_features |= FW_FEATURE_CMO;
> +		pSeries_coalesce_init();
>  	} else
>  		pr_debug("CMO not enabled, PrPSP=%d, SecPSP=%d\n", CMO_PrPSP,
>  		         CMO_SecPSP);
> diff -puN arch/powerpc/kernel/prom_init.c~powerpc_coalesce arch/powerpc/kernel/prom_init.c
> --- linux-2.6/arch/powerpc/kernel/prom_init.c~powerpc_coalesce	2011-04-20 08:38:42.000000000 -0500
> +++ linux-2.6-bjking1/arch/powerpc/kernel/prom_init.c	2011-04-20 08:38:42.000000000 -0500
> @@ -676,8 +676,10 @@ static void __init early_cmdline_parse(v
>  #endif /* CONFIG_PCI_MSI */
>  #ifdef CONFIG_PPC_SMLPAR
>  #define OV5_CMO			0x80	/* Cooperative Memory Overcommitment */
> +#define OV5_XCMO			0x40	/* Page Coalescing */
>  #else
>  #define OV5_CMO			0x00
> +#define OV5_XCMO			0x00
>  #endif
>  #define OV5_TYPE1_AFFINITY	0x80	/* Type 1 NUMA affinity */
>  
> @@ -732,7 +734,7 @@ static unsigned char ibm_architecture_ve
>  	OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY |
>  	OV5_DONATE_DEDICATE_CPU | OV5_MSI,
>  	0,
> -	OV5_CMO,
> +	OV5_CMO | OV5_XCMO,
>  	OV5_TYPE1_AFFINITY,
>  	0,
>  	0,
> diff -puN arch/powerpc/kernel/lparcfg.c~powerpc_coalesce arch/powerpc/kernel/lparcfg.c
> --- linux-2.6/arch/powerpc/kernel/lparcfg.c~powerpc_coalesce	2011-04-20 08:38:42.000000000 -0500
> +++ linux-2.6-bjking1/arch/powerpc/kernel/lparcfg.c	2011-04-20 08:38:42.000000000 -0500
> @@ -161,6 +161,21 @@ int h_get_mpp(struct hvcall_mpp_data *mp
>  }
>  EXPORT_SYMBOL(h_get_mpp);
>  
> +int h_get_mpp_x(struct hvcall_mpp_x_data *mpp_x_data)
> +{
> +	int rc;
> +	unsigned long retbuf[PLPAR_HCALL9_BUFSIZE] = { 0 };
> +
> +	rc = plpar_hcall9(H_GET_MPP_X, retbuf);
> +
> +	mpp_x_data->coalesced_bytes = retbuf[0];
> +	mpp_x_data->pool_coalesced_bytes = retbuf[1];
> +	mpp_x_data->pool_purr_cycles = retbuf[2];
> +	mpp_x_data->pool_spurr_cycles = retbuf[3];
> +
> +	return rc;
> +}
> +
>  struct hvcall_ppp_data {
>  	u64	entitlement;
>  	u64	unallocated_entitlement;
> @@ -345,6 +360,30 @@ static void parse_mpp_data(struct seq_fi
>  	seq_printf(m, "backing_memory=%ld bytes\n", mpp_data.backing_mem);
>  }
>  
> +/**
> + * parse_mpp_x_data
> + * Parse out data returned from h_get_mpp_x
> + */
> +static void parse_mpp_x_data(struct seq_file *m)
> +{
> +	struct hvcall_mpp_x_data mpp_x_data;
> +
> +	if (!firmware_has_feature(FW_FEATURE_XCMO))
> +		return;
> +	if (h_get_mpp_x(&mpp_x_data))
> +		return;
> +
> +	seq_printf(m, "coalesced_bytes=%ld\n", mpp_x_data.coalesced_bytes);
> +
> +	if (mpp_x_data.pool_coalesced_bytes)
> +		seq_printf(m, "pool_coalesced_bytes=%ld\n",
> +			   mpp_x_data.pool_coalesced_bytes);
> +	if (mpp_x_data.pool_purr_cycles)
> +		seq_printf(m, "coalesce_pool_purr=%ld\n", mpp_x_data.pool_purr_cycles);
> +	if (mpp_x_data.pool_spurr_cycles)
> +		seq_printf(m, "coalesce_pool_spurr=%ld\n", mpp_x_data.pool_spurr_cycles);
> +}
> +
>  #define SPLPAR_CHARACTERISTICS_TOKEN 20
>  #define SPLPAR_MAXLENGTH 1026*(sizeof(char))
>  
> @@ -520,6 +559,7 @@ static int pseries_lparcfg_data(struct s
>  		parse_system_parameter_string(m);
>  		parse_ppp_data(m);
>  		parse_mpp_data(m);
> +		parse_mpp_x_data(m);
>  		pseries_cmo_data(m);
>  		splpar_dispatch_data(m);
>  
> diff -puN arch/powerpc/include/asm/firmware.h~powerpc_coalesce arch/powerpc/include/asm/firmware.h
> --- linux-2.6/arch/powerpc/include/asm/firmware.h~powerpc_coalesce	2011-04-20 08:38:42.000000000 -0500
> +++ linux-2.6-bjking1/arch/powerpc/include/asm/firmware.h	2011-04-20 08:38:42.000000000 -0500
> @@ -47,6 +47,7 @@
>  #define FW_FEATURE_BEAT		ASM_CONST(0x0000000001000000)
>  #define FW_FEATURE_CMO		ASM_CONST(0x0000000002000000)
>  #define FW_FEATURE_VPHN		ASM_CONST(0x0000000004000000)
> +#define FW_FEATURE_XCMO		ASM_CONST(0x0000000008000000)
>  
>  #ifndef __ASSEMBLY__
>  
> @@ -60,7 +61,7 @@ enum {
>  		FW_FEATURE_VIO | FW_FEATURE_RDMA | FW_FEATURE_LLAN |
>  		FW_FEATURE_BULK_REMOVE | FW_FEATURE_XDABR |
>  		FW_FEATURE_MULTITCE | FW_FEATURE_SPLPAR | FW_FEATURE_LPAR |
> -		FW_FEATURE_CMO | FW_FEATURE_VPHN,
> +		FW_FEATURE_CMO | FW_FEATURE_VPHN | FW_FEATURE_XCMO,
>  	FW_FEATURE_PSERIES_ALWAYS = 0,
>  	FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
>  	FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
> diff -puN arch/powerpc/platforms/pseries/lpar.c~powerpc_coalesce arch/powerpc/platforms/pseries/lpar.c
> --- linux-2.6/arch/powerpc/platforms/pseries/lpar.c~powerpc_coalesce	2011-04-20 08:38:42.000000000 -0500
> +++ linux-2.6-bjking1/arch/powerpc/platforms/pseries/lpar.c	2011-04-20 08:38:42.000000000 -0500
> @@ -329,6 +329,8 @@ static long pSeries_lpar_hpte_insert(uns
>  	/* Make pHyp happy */
>  	if ((rflags & _PAGE_NO_CACHE) & !(rflags & _PAGE_WRITETHRU))
>  		hpte_r &= ~_PAGE_COHERENT;
> +	if (firmware_has_feature(FW_FEATURE_XCMO) && !(hpte_r & HPTE_R_N))
> +		flags |= H_COALESCE_CAND;
>  
>  	lpar_rc = plpar_pte_enter(flags, hpte_group, hpte_v, hpte_r, &slot);
>  	if (unlikely(lpar_rc == H_PTEG_FULL)) {
> diff -puN arch/powerpc/include/asm/pSeries_reconfig.h~powerpc_coalesce arch/powerpc/include/asm/pSeries_reconfig.h
> --- linux-2.6/arch/powerpc/include/asm/pSeries_reconfig.h~powerpc_coalesce	2011-04-20 08:38:42.000000000 -0500
> +++ linux-2.6-bjking1/arch/powerpc/include/asm/pSeries_reconfig.h	2011-04-20 08:38:42.000000000 -0500
> @@ -14,6 +14,12 @@
>  #define PSERIES_DRCONF_MEM_ADD		0x0003
>  #define PSERIES_DRCONF_MEM_REMOVE	0x0004
>  
> +#ifdef CONFIG_PPC_SMLPAR
> +extern void pSeries_coalesce_init(void);
> +#else
> +static inline void pSeries_coalesce_init(void) { }
> +#endif
> +
>  #ifdef CONFIG_PPC_PSERIES
>  extern int pSeries_reconfig_notifier_register(struct notifier_block *);
>  extern void pSeries_reconfig_notifier_unregister(struct notifier_block *);
> diff -puN arch/powerpc/kernel/rtas.c~powerpc_coalesce arch/powerpc/kernel/rtas.c
> --- linux-2.6/arch/powerpc/kernel/rtas.c~powerpc_coalesce	2011-04-20 08:38:42.000000000 -0500
> +++ linux-2.6-bjking1/arch/powerpc/kernel/rtas.c	2011-04-20 08:38:42.000000000 -0500
> @@ -42,6 +42,7 @@
>  #include <asm/time.h>
>  #include <asm/mmu.h>
>  #include <asm/topology.h>
> +#include <asm/pSeries_reconfig.h>
>  
>  struct rtas_t rtas = {
>  	.lock = __ARCH_SPIN_LOCK_UNLOCKED
> @@ -731,6 +732,7 @@ static int __rtas_suspend_last_cpu(struc
>  
>  	atomic_set(&data->error, rc);
>  	start_topology_update();
> +	pSeries_coalesce_init();
>  
>  	if (wake_when_done) {
>  		atomic_set(&data->done, 1);
> _

^ permalink raw reply

* [PATCH] powerpc/85xx: ULPI PHY support for P101x platforms
From: Ramneek Mehresh @ 2011-04-23 12:33 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Ramneek Mehresh

Add support for USB ULPI (external) PHY for P101x platforms
 - for both USB Host and Peripheral modes

Signed-off-by: Ramneek Mehresh <ramneek.mehresh@freescale.com>
---
Applies on git://git.am.freescale.net/mirrors/linux-2.6.git
(branch master)

 drivers/usb/gadget/fsl_udc_core.c |    6 ++++++
 drivers/usb/gadget/fsl_usb2_udc.h |    1 +
 drivers/usb/host/ehci-fsl.c       |    5 +++++
 drivers/usb/host/ehci-fsl.h       |    1 +
 4 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index c669600..4f7578a 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -189,6 +189,12 @@ static int dr_controller_setup(struct fsl_udc *udc)
 	portctrl &= ~(PORTSCX_PHY_TYPE_SEL | PORTSCX_PORT_WIDTH);
 	switch (udc->phy_mode) {
 	case FSL_USB2_PHY_ULPI:
+#ifdef CONFIG_PPC_85xx
+		ctrl = __raw_readl(&usb_sys_regs->control);
+		ctrl &= ~USB_CTRL_UTMI_PHY_EN;
+		ctrl |= USB_CTRL_ULPI_PHY_CLK_SEL;
+		__raw_writel(ctrl, &usb_sys_regs->control);
+#endif
 		portctrl |= PORTSCX_PTS_ULPI;
 		break;
 	case FSL_USB2_PHY_UTMI_WIDE:
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
index d489c62..031c256 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/fsl_usb2_udc.h
@@ -365,6 +365,7 @@ struct usb_sys_interface {
 #define  USB_CTRL_ULPI_INT0EN                 0x00000001
 #define USB_CTRL_UTMI_PHY_EN		      0x00000200
 #define USB_CTRL_USB_EN			      0x00000004
+#define USB_CTRL_ULPI_PHY_CLK_SEL		0x00000400
 
 /* Endpoint Queue Head data struct
  * Rem: all the variables of qh are LittleEndian Mode
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 55f4ab5..a755b9d 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -190,6 +190,11 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
 	portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
 	switch (phy_mode) {
 	case FSL_USB2_PHY_ULPI:
+#ifdef CONFIG_PPC_85xx
+		temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
+		out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | USB_CTRL_USB_EN |
+				ULPI_PHY_CLK_SEL);
+#endif
 		portsc |= PORT_PTS_ULPI;
 		break;
 	case FSL_USB2_PHY_SERIAL:
diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
index 06a94e9..6ed589c 100644
--- a/drivers/usb/host/ehci-fsl.h
+++ b/drivers/usb/host/ehci-fsl.h
@@ -52,4 +52,5 @@
 #define OTG_PORT		(1<<5)
 #define PLL_RESET		(1<<8)
 #define UTMI_PHY_EN		(1<<9)
+#define ULPI_PHY_CLK_SEL	(1<<10)
 #endif				/* _EHCI_FSL_H */
-- 
1.6.1

^ permalink raw reply related

* [PATCH] powerpc/85xx: Add UTMI PHY support for 85xx platforms
From: Ramneek Mehresh @ 2011-04-23 12:33 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Ramneek Mehresh

Add UTMI internal PHY support for P5020/P3041/P101x platforms.
 - for both USB Host and Peripheral modes

Signed-off-by: Ramneek Mehresh <ramneek.mehresh@freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
---
Applies on git://git.am.freescale.net/mirrors/linux-2.6.git
(branch master)

 drivers/usb/gadget/fsl_udc_core.c |    7 ++++++-
 drivers/usb/gadget/fsl_usb2_udc.h |   19 +++++++++++++++++++
 drivers/usb/host/ehci-fsl.c       |   10 ++++++++--
 drivers/usb/host/ehci-fsl.h       |   12 +++++++++++-
 4 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 07499c1..c669600 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007 Freescale Semicondutor, Inc. All rights reserved.
+ * Copyright (C) 2004-2011 Freescale Semiconductor, Inc.
  *
  * Author: Li Yang <leoli@freescale.com>
  *         Jiang Bo <tanya.jiang@freescale.com>
@@ -195,6 +195,11 @@ static int dr_controller_setup(struct fsl_udc *udc)
 		portctrl |= PORTSCX_PTW_16BIT;
 		/* fall through */
 	case FSL_USB2_PHY_UTMI:
+#ifdef CONFIG_PPC_85xx
+		setbits32(&usb_sys_regs->control, USB_CTRL_UTMI_PHY_EN |
+				USB_CTRL_USB_EN);
+		udelay(10*1000);  /* delay for PHY clk to ready */
+#endif
 		portctrl |= PORTSCX_PTS_UTMI;
 		break;
 	case FSL_USB2_PHY_SERIAL:
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
index e88cce5..d489c62 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/fsl_usb2_udc.h
@@ -1,3 +1,20 @@
+/* Copyright (C) 2011 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 as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the  GNU General Public License along
+ * with this program; if not, write  to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
 /*
  * Freescale USB device/endpoint management registers
  */
@@ -346,6 +363,8 @@ struct usb_sys_interface {
 /* control Register Bit Masks */
 #define  USB_CTRL_IOENB                       0x00000004
 #define  USB_CTRL_ULPI_INT0EN                 0x00000001
+#define USB_CTRL_UTMI_PHY_EN		      0x00000200
+#define USB_CTRL_USB_EN			      0x00000004
 
 /* Endpoint Queue Head data struct
  * Rem: all the variables of qh are LittleEndian Mode
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 5c761df..55f4ab5 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -1,6 +1,6 @@
 /*
  * Copyright 2005-2009 MontaVista Software, Inc.
- * Copyright 2008      Freescale Semiconductor, Inc.
+ * Copyright 2011      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 as published by the
@@ -183,10 +183,11 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
 			       unsigned int port_offset)
 {
 	u32 portsc;
+	struct usb_hcd *hcd = ehci_to_hcd(ehci);
+	void __iomem *non_ehci = hcd->regs;
 
 	portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
 	portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
-
 	switch (phy_mode) {
 	case FSL_USB2_PHY_ULPI:
 		portsc |= PORT_PTS_ULPI;
@@ -198,6 +199,11 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
 		portsc |= PORT_PTS_PTW;
 		/* fall through */
 	case FSL_USB2_PHY_UTMI:
+#ifdef CONFIG_PPC_85xx
+		setbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN |
+				USB_CTRL_USB_EN);
+		udelay(10*1000);  /* delay for PHY clk to ready */
+#endif
 		portsc |= PORT_PTS_UTMI;
 		break;
 	case FSL_USB2_PHY_NONE:
diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
index 3fabed3..06a94e9 100644
--- a/drivers/usb/host/ehci-fsl.h
+++ b/drivers/usb/host/ehci-fsl.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005-2010 Freescale Semiconductor, Inc.
+/* Copyright (C) 2005-2011 Freescale Semiconductor, Inc.
  * Copyright (c) 2005 MontaVista Software
  *
  * This program is free software; you can redistribute  it and/or modify it
@@ -42,4 +42,14 @@
 #define FSL_SOC_USB_SICTRL	0x410	/* NOTE: big-endian */
 #define FSL_SOC_USB_CTRL	0x500	/* NOTE: big-endian */
 #define SNOOP_SIZE_2GB		0x1e
+
+/* control Register Bit Masks */
+#define ULPI_INT_EN		(1<<0)
+#define WU_INT_EN		(1<<1)
+#define USB_CTRL_USB_EN		(1<<2)
+#define LINE_STATE_FILTER__EN	(1<<3)
+#define KEEP_OTG_ON		(1<<4)
+#define OTG_PORT		(1<<5)
+#define PLL_RESET		(1<<8)
+#define UTMI_PHY_EN		(1<<9)
 #endif				/* _EHCI_FSL_H */
-- 
1.6.1

^ permalink raw reply related

* [PATCH] [v1] powerpc/85xx: Add ULPI PHY support for P101x platforms
From: Ramneek Mehresh @ 2011-04-23 13:48 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Ramneek Mehresh

Add support for USB ULPI (external) PHY for P101x platforms
 - for both USB Host and Peripheral modes

Signed-off-by: Ramneek Mehresh <ramneek.mehresh@freescale.com>
---
Changes for v1:
	- removing the usage of variable temp

Applies on git://git.am.freescale.net/mirrors/linux-2.6.git
(branch master)

 drivers/usb/gadget/fsl_udc_core.c |    6 ++++++
 drivers/usb/gadget/fsl_usb2_udc.h |    1 +
 drivers/usb/host/ehci-fsl.c       |    5 +++++
 drivers/usb/host/ehci-fsl.h       |    1 +
 4 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index c669600..4f7578a 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -189,6 +189,12 @@ static int dr_controller_setup(struct fsl_udc *udc)
 	portctrl &= ~(PORTSCX_PHY_TYPE_SEL | PORTSCX_PORT_WIDTH);
 	switch (udc->phy_mode) {
 	case FSL_USB2_PHY_ULPI:
+#ifdef CONFIG_PPC_85xx
+		ctrl = __raw_readl(&usb_sys_regs->control);
+		ctrl &= ~USB_CTRL_UTMI_PHY_EN;
+		ctrl |= USB_CTRL_ULPI_PHY_CLK_SEL;
+		__raw_writel(ctrl, &usb_sys_regs->control);
+#endif
 		portctrl |= PORTSCX_PTS_ULPI;
 		break;
 	case FSL_USB2_PHY_UTMI_WIDE:
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
index d489c62..78e55ba 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/fsl_usb2_udc.h
@@ -365,6 +365,7 @@ struct usb_sys_interface {
 #define  USB_CTRL_ULPI_INT0EN                 0x00000001
 #define USB_CTRL_UTMI_PHY_EN		      0x00000200
 #define USB_CTRL_USB_EN			      0x00000004
+#define USB_CTRL_ULPI_PHY_CLK_SEL	      0x00000400
 
 /* Endpoint Queue Head data struct
  * Rem: all the variables of qh are LittleEndian Mode
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 55f4ab5..d698ac8 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -190,6 +190,11 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
 	portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
 	switch (phy_mode) {
 	case FSL_USB2_PHY_ULPI:
+#ifdef CONFIG_PPC_85xx
+		out_be32(non_ehci + FSL_SOC_USB_CTRL,
+			in_be32(non_ehci + FSL_SOC_USB_CTRL) |
+			USB_CTRL_USB_EN | ULPI_PHY_CLK_SEL);
+#endif
 		portsc |= PORT_PTS_ULPI;
 		break;
 	case FSL_USB2_PHY_SERIAL:
diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
index 06a94e9..6ed589c 100644
--- a/drivers/usb/host/ehci-fsl.h
+++ b/drivers/usb/host/ehci-fsl.h
@@ -52,4 +52,5 @@
 #define OTG_PORT		(1<<5)
 #define PLL_RESET		(1<<8)
 #define UTMI_PHY_EN		(1<<9)
+#define ULPI_PHY_CLK_SEL	(1<<10)
 #endif				/* _EHCI_FSL_H */
-- 
1.6.1

^ permalink raw reply related

* Re: [PATCH] powerpc: Add Initiate Coprocessor Store Word (icswx) support
From: Benjamin Herrenschmidt @ 2011-04-24  6:05 UTC (permalink / raw)
  To: Anton Blanchard; +Cc: tsenglin, linuxppc-dev
In-Reply-To: <20110418113638.29c0bc85@kryten>

On Mon, 2011-04-18 at 11:36 +1000, Anton Blanchard wrote:
> - By including linux/spinlock_types.h we can remove the dynamic
> allocation
>   of the spinlock hack and simplify things a lot.

Causes all sort of hell for me on some configs. Lockdep is not happy for
example and there's some nasty include dependency circles. Not sure
that's fixable at least not without some important cleanup of how
mmu_context_t is defined.

Ben.

^ permalink raw reply

* Re: [PATCH 3/5] powerpc, hw_breakpoints: Fix racy access to ptrace breakpoints
From: K.Prasad @ 2011-04-24  8:04 UTC (permalink / raw)
  To: Frederic Weisbecker
  Cc: Peter Zijlstra, Will Deacon, LKML, Oleg Nesterov, Paul Mundt,
	Ingo Molnar, LPPC, v2.6.33..
In-Reply-To: <1303478187-2367-1-git-send-email-fweisbec@gmail.com>

On Fri, Apr 22, 2011 at 03:16:27PM +0200, Frederic Weisbecker wrote:
> (resend with ppc list in cc)
> 
> While the tracer accesses ptrace breakpoints, the child task may
> concurrently exit due to a SIGKILL and thus release its breakpoints
> at the same time. We can then dereference some freed pointers.
> 
> To fix this, hold a reference on the child breakpoints before
> manipulating them.
> 
> Reported-by: Oleg Nesterov <oleg@redhat.com>
> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
> Cc: Ingo Molnar <mingo@elte.hu>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Prasad <prasad@linux.vnet.ibm.com>
> Cc: Paul Mundt <lethal@linux-sh.org>
> Cc: v2.6.33.. <stable@kernel.org>
> ---
>  arch/powerpc/kernel/ptrace.c |    3 +++
>  1 files changed, 3 insertions(+), 0 deletions(-)
>
> diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
> index 55613e3..4edeeb3 100644
> --- a/arch/powerpc/kernel/ptrace.c
> +++ b/arch/powerpc/kernel/ptrace.c
> @@ -1591,7 +1591,10 @@ long arch_ptrace(struct task_struct *child, long request,
>  	}
> 
>  	case PTRACE_SET_DEBUGREG:
> +		if (ptrace_get_breakpoints(child) < 0)
> +			return -ESRCH;
>  		ret = ptrace_set_debugreg(child, addr, data);
> +		ptrace_put_breakpoints(child);
>  		break;
> 
>  #ifdef CONFIG_PPC64
> -- 
> 1.7.3.2
>

Hi Frederic,
	Looks fine to me.

Acked-by: K.Prasad <prasad@linux.vnet.ibm.com>

Thanks,
K.Prasad 

^ permalink raw reply

* [PATCH] powerpc/kexec: Fix build failure on 32-bit SMP
From: Ben Hutchings @ 2011-04-25  1:04 UTC (permalink / raw)
  To: Paul Gortmaker, Benjamin Herrenschmidt; +Cc: linuxppc-dev

Commit b987812b3fcaf70fdf0037589e5d2f5f2453e6ce left
crash_kexec_wait_realmode() undefined for UP.

Commit 7c7a81b53e581d727d069cc45df5510516faac31 defined it for UP but
left it undefined for 32-bit SMP.

Seems like people are getting confused by nested #ifdef's, so move the
definitions of crash_kexec_wait_realmode() after the #ifdef CONFIG_SMP
section.

Compile-tested with 32-bit UP, 32-bit SMP and 64-bit SMP configurations.

Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
--- a/arch/powerpc/kernel/crash.c
+++ b/arch/powerpc/kernel/crash.c
@@ -162,34 +162,6 @@
 	/* Leave the IPI callback set */
 }
=20
-/* wait for all the CPUs to hit real mode but timeout if they don't come i=
n */
-#ifdef CONFIG_PPC_STD_MMU_64
-static void crash_kexec_wait_realmode(int cpu)
-{
-	unsigned int msecs;
-	int i;
-
-	msecs =3D 10000;
-	for (i=3D0; i < NR_CPUS && msecs > 0; i++) {
-		if (i =3D=3D cpu)
-			continue;
-
-		while (paca[i].kexec_state < KEXEC_STATE_REAL_MODE) {
-			barrier();
-			if (!cpu_possible(i)) {
-				break;
-			}
-			if (!cpu_online(i)) {
-				break;
-			}
-			msecs--;
-			mdelay(1);
-		}
-	}
-	mb();
-}
-#endif	/* CONFIG_PPC_STD_MMU_64 */
-
 /*
  * This function will be called by secondary cpus or by kexec cpu
  * if soft-reset is activated to stop some CPUs.
@@ -234,7 +206,6 @@
 }
=20
 #else	/* ! CONFIG_SMP */
-static inline void crash_kexec_wait_realmode(int cpu) {}
=20
 static void crash_kexec_prepare_cpus(int cpu)
 {
@@ -257,6 +228,36 @@
 }
 #endif	/* CONFIG_SMP */
=20
+/* wait for all the CPUs to hit real mode but timeout if they don't come i=
n */
+#if defined(CONFIG_SMP) && defined(CONFIG_PPC_STD_MMU_64)
+static void crash_kexec_wait_realmode(int cpu)
+{
+	unsigned int msecs;
+	int i;
+
+	msecs =3D 10000;
+	for (i=3D0; i < NR_CPUS && msecs > 0; i++) {
+		if (i =3D=3D cpu)
+			continue;
+
+		while (paca[i].kexec_state < KEXEC_STATE_REAL_MODE) {
+			barrier();
+			if (!cpu_possible(i)) {
+				break;
+			}
+			if (!cpu_online(i)) {
+				break;
+			}
+			msecs--;
+			mdelay(1);
+		}
+	}
+	mb();
+}
+#else
+static inline void crash_kexec_wait_realmode(int cpu) {}
+#endif	/* CONFIG_SMP && CONFIG_PPC_STD_MMU_64 */
+
 /*
  * Register a function to be called on shutdown.  Only use this if you
  * can't reset your device in the second kernel.

--=20
Ben Hutchings
Once a job is fouled up, anything done to improve it makes it worse.

^ permalink raw reply

* Re: [PATCH 1/1] powerpc: Add page coalescing support
From: Brian King @ 2011-04-25 14:03 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1303513178.2513.92.camel@pasglop>

On 04/22/2011 05:59 PM, Benjamin Herrenschmidt wrote:
> On Fri, 2011-04-22 at 16:08 -0500, Brian King wrote:
>> Adds support for page coalescing, which is a feature on IBM Power servers
>> which allows for coalescing identical pages between logical partitions.
>> Hint text pages as coalesce candidates, since they are the most likely
>> pages to be able to be coalesced between partitions. This patch also
>> exports some page coalescing statistics available from firmware via
>> lparcfg.
> 
> Hi Brian !
> 
> Is this patch different from the version you posted previously which is
> already on Patchwork ? I'm in the process of putting together
> powerpc-next and your previous variant is in my queue.

Its the same, just a repost.

Thanks,

Brian

-- 
Brian King
Linux on Power Virtualization
IBM Linux Technology Center

^ permalink raw reply

* device not available because of BAR 0 collisions
From: Steven A. Falco @ 2011-04-25 20:10 UTC (permalink / raw)
  To: linuxppc-dev

I'm getting an error message when trying to talk to some custom hardware:

dx83xx 0001:43:00.0: device not available because of BAR 0 [0xa1000000-0xa1ffffff] collisions

I see in setup-res.c that this message comes out when there is no parent for
a device resource.

I've been digging around in the code, and I confess that I cannot figure out
where the parent member is assigned.  Can someone please give me a hint as to
where the assignment happens?

The hardware consists of a pair of ASICs attached to a PPC405EX via a PCIe switch.
The device tree is based on the Kilauea evaluation board.  The device tree does not
specify the PCIe switch or ASICs.

Do I need to add something to the device tree to represent the PCIe switch, or
should it be automatically discovered and configured?

U-Boot reports the PCI hardware as:

PCIE0: successfully set as root-complex
        01  00  1172  0004  ff00  00
PCIE1: successfully set as root-complex
        05  00  1b03  7000  0000  ff
        04  01  10b5  8613  0604  00
        06  00  1b03  7000  0000  ff
        04  02  10b5  8613  0604  00
        03  00  10b5  8613  0604  00

The PCIe switch shows up as 03:00, 04:01, and 04:02.  The ASICs show up as 05:00 and
06:00, so there is no problem with config-space that I can see.

Similar hardware (an evaluation board for the ASICs) works ok on an x86 PC.  The
PCIe switch is recognized, and the ASIC driver probes and enables the device
without any problems.  Sadly, I cannot plug it into the Kilauea because it needs a
PCIe x16 slot.

Guidance gratefully accepted!

	Steve


-- 
A: Because it makes the logic of the discussion difficult to follow.
Q: Why shouldn't I top post?
A: No.
Q: Should I top post?

^ permalink raw reply

* Re: device not available because of BAR 0 collisions
From: Benjamin Herrenschmidt @ 2011-04-26  0:01 UTC (permalink / raw)
  To: Steven A. Falco; +Cc: linuxppc-dev
In-Reply-To: <4DB5D548.7020303@harris.com>

On Mon, 2011-04-25 at 16:10 -0400, Steven A. Falco wrote:
> I'm getting an error message when trying to talk to some custom
> hardware:
> 
> dx83xx 0001:43:00.0: device not available because of BAR 0
> [0xa1000000-0xa1ffffff] collisions
> 
> I see in setup-res.c that this message comes out when there is no
> parent for
> a device resource.

 .../...

It mostly happens in arch/powerpc/kernel/pci-common.c and the generic
setup-res.c

Try #define DEBUG at the top (before the #includes) of pci-common.c and
pci_32.c (remove the exiting #undef in the last one) and send us the
full dmesg log, along with the output of cat /proc/iomem

Cheers,
Ben.

^ permalink raw reply

* [PATCH] powerpc/44x: Add multiple chip select support to NDFC driver
From: Felix Radensky @ 2011-04-26  9:36 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Felix Radensky, sr, linux-mtd

This patch extends NDFC driver to support all 4 chip selects
available in NDFC NAND controller. Tested on custom 460EX board
with 2 chip select NAND device.

Signed-off-by: Felix Radensky <felix@embedded-sol.com>
---

I'd appreciate some testing on 44x boards with multiple NAND
devices, like bamboo or DU440, as I don't have access to these 
boards.

 drivers/mtd/nand/ndfc.c |   52 +++++++++++++++++++++++++++++++---------------
 1 files changed, 35 insertions(+), 17 deletions(-)

diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index bbe6d45..5e0be1e 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -33,6 +33,7 @@
 #include <linux/of_platform.h>
 #include <asm/io.h>
 
+#define NDFC_MAX_CS    4
 
 struct ndfc_controller {
 	struct platform_device *ofdev;
@@ -46,12 +47,13 @@ struct ndfc_controller {
 #endif
 };
 
-static struct ndfc_controller ndfc_ctrl;
+static struct ndfc_controller ndfc_ctrl[NDFC_MAX_CS];
 
 static void ndfc_select_chip(struct mtd_info *mtd, int chip)
 {
 	uint32_t ccr;
-	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	struct nand_chip *nchip = mtd->priv;
+	struct ndfc_controller *ndfc = nchip->priv;
 
 	ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
 	if (chip >= 0) {
@@ -64,7 +66,8 @@ static void ndfc_select_chip(struct mtd_info *mtd, int chip)
 
 static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
-	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	struct nand_chip *chip = mtd->priv;
+	struct ndfc_controller *ndfc = chip->priv;
 
 	if (cmd == NAND_CMD_NONE)
 		return;
@@ -77,7 +80,8 @@ static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 
 static int ndfc_ready(struct mtd_info *mtd)
 {
-	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	struct nand_chip *chip = mtd->priv;
+	struct ndfc_controller *ndfc = chip->priv;
 
 	return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY;
 }
@@ -85,7 +89,8 @@ static int ndfc_ready(struct mtd_info *mtd)
 static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
 {
 	uint32_t ccr;
-	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	struct nand_chip *chip = mtd->priv;
+	struct ndfc_controller *ndfc = chip->priv;
 
 	ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
 	ccr |= NDFC_CCR_RESET_ECC;
@@ -96,7 +101,8 @@ static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
 static int ndfc_calculate_ecc(struct mtd_info *mtd,
 			      const u_char *dat, u_char *ecc_code)
 {
-	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	struct nand_chip *chip = mtd->priv;
+	struct ndfc_controller *ndfc = chip->priv;
 	uint32_t ecc;
 	uint8_t *p = (uint8_t *)&ecc;
 
@@ -119,7 +125,8 @@ static int ndfc_calculate_ecc(struct mtd_info *mtd,
  */
 static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	struct nand_chip *chip = mtd->priv;
+	struct ndfc_controller *ndfc = chip->priv;
 	uint32_t *p = (uint32_t *) buf;
 
 	for(;len > 0; len -= 4)
@@ -128,7 +135,8 @@ static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 
 static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
-	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	struct nand_chip *chip = mtd->priv;
+	struct ndfc_controller *ndfc = chip->priv;
 	uint32_t *p = (uint32_t *) buf;
 
 	for(;len > 0; len -= 4)
@@ -137,7 +145,8 @@ static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 
 static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
-	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	struct nand_chip *chip = mtd->priv;
+	struct ndfc_controller *ndfc = chip->priv;
 	uint32_t *p = (uint32_t *) buf;
 
 	for(;len > 0; len -= 4)
@@ -179,6 +188,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
 	chip->ecc.mode = NAND_ECC_HW;
 	chip->ecc.size = 256;
 	chip->ecc.bytes = 3;
+	chip->priv = ndfc;
 
 	ndfc->mtd.priv = chip;
 	ndfc->mtd.owner = THIS_MODULE;
@@ -227,15 +237,10 @@ err:
 
 static int __devinit ndfc_probe(struct platform_device *ofdev)
 {
-	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	struct ndfc_controller *ndfc;
 	const __be32 *reg;
 	u32 ccr;
-	int err, len;
-
-	spin_lock_init(&ndfc->ndfc_control.lock);
-	init_waitqueue_head(&ndfc->ndfc_control.wq);
-	ndfc->ofdev = ofdev;
-	dev_set_drvdata(&ofdev->dev, ndfc);
+	int err, len, cs;
 
 	/* Read the reg property to get the chip select */
 	reg = of_get_property(ofdev->dev.of_node, "reg", &len);
@@ -243,8 +248,21 @@ static int __devinit ndfc_probe(struct platform_device *ofdev)
 		dev_err(&ofdev->dev, "unable read reg property (%d)\n", len);
 		return -ENOENT;
 	}
-	ndfc->chip_select = be32_to_cpu(reg[0]);
 
+	cs = be32_to_cpu(reg[0]);
+	if (cs >= NDFC_MAX_CS) {
+		dev_err(&ofdev->dev, "invalid CS number (%d)\n", cs);
+		return -EINVAL;
+	}
+
+	ndfc = &ndfc_ctrl[cs];
+	ndfc->chip_select = cs;
+
+	spin_lock_init(&ndfc->ndfc_control.lock);
+	init_waitqueue_head(&ndfc->ndfc_control.wq);
+	ndfc->ofdev = ofdev;
+	dev_set_drvdata(&ofdev->dev, ndfc);
+	
 	ndfc->ndfcbase = of_iomap(ofdev->dev.of_node, 0);
 	if (!ndfc->ndfcbase) {
 		dev_err(&ofdev->dev, "failed to get memory\n");
-- 
1.7.4.4

^ permalink raw reply related

* Re: [PATCH 11/14] PM / AVR32: Use struct syscore_ops instead of sysdevs for PM
From: Hans-Christian Egtvedt @ 2011-04-26 12:22 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Kevin Hilman, Guan Xuetao, Russell King, Konrad Rzeszutek Wilk,
	Greg KH, LKML, Ralf Baechle, Jeremy Fitzhardinge, Ben Dooks,
	Jiri Kosina, Kay Sievers, Mike Frysinger, Linux PM mailing list,
	linux-omap, linuxppc-dev, linux-arm-kernel
In-Reply-To: <201104172313.09712.rjw@sisk.pl>

On Sun, 2011-04-17 at 23:13 +0200, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rjw@sisk.pl>
> 
> Convert some AVR32 architecture's code to using struct syscore_ops
> objects for power management instead of sysdev classes and sysdevs.
> 
> This simplifies the code and reduces the kernel's memory footprint.
> It also is necessary for removing sysdevs from the kernel entirely in
> the future.
> 
> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>

Acked-by: Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>

Thanks, nice work. Tested and run on hardware.

<snipp>

-- 
Hans-Christian Egtvedt

^ permalink raw reply

* Re: device not available because of BAR 0 collisions
From: Steven A. Falco @ 2011-04-26 13:38 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1303776114.2513.152.camel@pasglop>

On 04/25/2011 08:01 PM, Benjamin Herrenschmidt wrote:
> On Mon, 2011-04-25 at 16:10 -0400, Steven A. Falco wrote:
>> I'm getting an error message when trying to talk to some custom
>> hardware:
>>
>> dx83xx 0001:43:00.0: device not available because of BAR 0
>> [0xa1000000-0xa1ffffff] collisions
>>
>> I see in setup-res.c that this message comes out when there is no
>> parent for
>> a device resource.
> 
>  .../...
> 
> It mostly happens in arch/powerpc/kernel/pci-common.c and the generic
> setup-res.c
> 
> Try #define DEBUG at the top (before the #includes) of pci-common.c and
> pci_32.c (remove the exiting #undef in the last one) and send us the
> full dmesg log, along with the output of cat /proc/iomem
> 
> Cheers,
> Ben.
> 
> 
> 

Thanks for the help!

PCIe 0 has an FPGA connected - it is behaving as expected.  PCIe 1 has the
PLX PCIe switch followed by a pair of ASICs - they are the ones generating
the error.

Here is /proc/iomem:

90000000-9fffffff : /plb/pciex@0c0000000
  90000000-93ffffff : PCI Bus 0001:41
    90000000-93ffffff : PCI Bus 0001:42
      90000000-91ffffff : PCI Bus 0001:43
      92000000-93ffffff : PCI Bus 0001:44
  94000000-940fffff : PCI Bus 0001:41
    94000000-9401ffff : 0001:41:00.0
e0000000-e7ffffff : /plb/pciex@0a0000000
  e0000000-e5ffffff : PCI Bus 0000:01
    e0000000-e3ffffff : 0000:01:00.0
    e4000000-e40fffff : 0000:01:00.0
    e4100000-e41fffff : 0000:01:00.0
ef600200-ef600207 : serial
ef600300-ef600307 : serial
ef600600-ef600606 : spi_ppc4xx_of
ef6c0000-ef6cffff : dwc_otg.0
  ef6c0000-ef6cffff : dwc_otg
fc000000-ffffffff : fc000000.nor_flash

And here is dmesg, captured after the failed modprobe, so you can see
those error messages (DEBUG enabled in pci-common.c and pci_32.c):

Using Flex-AM machine description
Linux version 2.6.30.3-00063-g0af2edc-dirty (sfalco@hw1.cs.myharris.net) (gcc version 4.2.2) #35 Tue Apr 26 09:20:23 EDT 2011
Found initrd at 0xcfba0000:0xcfea1872
Found legacy serial port 0 for /plb/opb/serial@ef600200
  mem=ef600200, taddr=ef600200, irq=0, clk=33333333, speed=0
Found legacy serial port 1 for /plb/opb/serial@ef600300
  mem=ef600300, taddr=ef600300, irq=0, clk=33333333, speed=0
Top of RAM: 0x10000000, Total RAM: 0x10000000
Memory hole size: 0MB
Zone PFN ranges:
  DMA      0x00000000 -> 0x00010000
  Normal   0x00010000 -> 0x00010000
Movable zone start PFN for each node
early_node_map[1] active PFN ranges
    0: 0x00000000 -> 0x00010000
On node 0 totalpages: 65536
free_area_init_node: node 0, pgdat c0406bdc, node_mem_map c0443000
  DMA zone: 512 pages used for memmap
  DMA zone: 0 pages reserved
  DMA zone: 65024 pages, LIFO batch:15
MMU: Allocated 1088 bytes of context maps for 255 contexts
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 65024
Kernel command line: root=/dev/sda2 rw ip=137.237.178.150:137.237.178.9:137.237.178.1:255.255.255.0:flx-am:eth0:off panic=1 console=ttyS1,115200 debug
NR_IRQS:512
UIC0 (32 IRQ sources) at DCR 0xc0
UIC1 (32 IRQ sources) at DCR 0xd0
irq: irq 30 on host /interrupt-controller mapped to virtual irq 30
UIC2 (32 IRQ sources) at DCR 0xe0
irq: irq 28 on host /interrupt-controller mapped to virtual irq 28
PID hash table entries: 1024 (order: 10, 4096 bytes)
time_init: decrementer frequency = 400.000000 MHz
time_init: processor frequency   = 400.000000 MHz
clocksource: timebase mult[a00000] shift[22] registered
clockevent: decrementer mult[6666] shift[16] cpu[0]
I-pipe 2.7-02: pipeline enabled.
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
Memory: 252092k/262144k available (3944k kernel code, 9744k reserved, 184k data, 204k bss, 164k init)
Kernel virtual memory layout:
  * 0xffffe000..0xfffff000  : fixmap
  * 0xfde00000..0xfe000000  : consistent mem
  * 0xfde00000..0xfde00000  : early ioremap
  * 0xd1000000..0xfde00000  : vmalloc & ioremap
SLUB: Genslabs=11, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
Calibrating delay loop... 798.72 BogoMIPS (lpj=1597440)
Mount-cache hash table entries: 512
net_namespace: 520 bytes
NET: Registered protocol family 16
PCIE0: Checking link...
PCIE0: Device detected, waiting for link...
PCIE0: link is up !
PCI host bridge /plb/pciex@0a0000000 (primary) ranges:
 MEM 0x00000000e0000000..0x00000000e7ffffff -> 0x0000000080000000
  IO 0x00000000e8000000..0x00000000e800ffff -> 0x0000000000000000
4xx PCI DMA offset set to 0x00000000
PCIE0: successfully set as root-complex
PCIE1: Checking link...
PCIE1: Device detected, waiting for link...
PCIE1: link is up !
PCI host bridge /plb/pciex@0c0000000 (primary) ranges:
 MEM 0x0000000090000000..0x000000009fffffff -> 0x0000000080000000
  IO 0x00000000e8010000..0x00000000e801ffff -> 0x0000000000000000
4xx PCI DMA offset set to 0x00000000
PCIE1: successfully set as root-complex
PCI: Probing PCI hardware
PCI: Scanning PHB /plb/pciex@0a0000000
PCI: PHB IO resource    = 00000000fffe0000-00000000fffeffff [100]
PCI: PHB MEM resource 0 = 00000000e0000000-00000000e7ffffff [200]
PCI: PHB MEM offset     = 0000000060000000
PCI: PHB IO  offset     = fffe0000
pci 0000:00:00.0: reg 10 32bit mmio: [0x000000-0x7fffffff]
PCI:0000:00:00.0 Resource 0 0000000000000000-000000007fffffff [21208] is unassigned
PCI: Hiding 4xx host bridge resources 0000:00:00.0
PCI: Fixup bus devices 0 (PHB)
pci_busdev_to_OF_node(0,0x0)
 parent is /plb/pciex@0a0000000
 result is <NULL>
PCI: Try to map irq for 0000:00:00.0...
pci_busdev_to_OF_node(0,0x0)
 parent is /plb/pciex@0a0000000
 result is <NULL>
pci 0000:01:00.0: reg 10 32bit mmio: [0x80000000-0x800fffff]
pci 0000:01:00.0: reg 14 32bit mmio: [0x80100000-0x801fffff]
pci 0000:01:00.0: reg 18 32bit mmio: [0x84000000-0x87ffffff]
PCI:0000:01:00.0 Resource 0 0000000080000000-00000000800fffff [20200] fixup...
PCI:0000:01:00.0            00000000e0000000-00000000e00fffff
PCI:0000:01:00.0 Resource 1 0000000080100000-00000000801fffff [20200] fixup...
PCI:0000:01:00.0            00000000e0100000-00000000e01fffff
PCI:0000:01:00.0 Resource 2 0000000084000000-0000000087ffffff [20200] fixup...
PCI:0000:01:00.0            00000000e4000000-00000000e7ffffff
pci 0000:00:00.0: bridge io port: [0x00-0xfff]
pci 0000:00:00.0: bridge 32bit mmio: [0x80000000-0x87ffffff]
PCI:0000:00:00.0 Bus rsrc 0 0000000000000000-0000000000000fff [101] fixup...
PCI:0000:00:00.0            00000000fffe0000-00000000fffe0fff
PCI:0000:00:00.0 Bus rsrc 1 0000000080000000-0000000087ffffff [200] fixup...
PCI:0000:00:00.0            00000000e0000000-00000000e7ffffff
PCI: Fixup bus devices 1 (0000:00:00.0)
pci_busdev_to_OF_node(1,0x0)
PCI: Try to map irq for 0000:01:00.0...
pci_busdev_to_OF_node(1,0x0)
pci_busdev_to_OF_node(0,0x0)
 parent is /plb/pciex@0a0000000
 result is <NULL>
 Got one, spec 2 cells (0x00000000 0x00000004...) on /interrupt-controller2
irq: irq 0 on host /interrupt-controller2 mapped to virtual irq 16
 Mapped to linux irq 16
PCI: Scanning PHB /plb/pciex@0c0000000
PCI: PHB IO resource    = 0000000000000000-000000000000ffff [100]
PCI: PHB MEM resource 0 = 0000000090000000-000000009fffffff [200]
PCI: PHB MEM offset     = 0000000010000000
PCI: PHB IO  offset     = 00000000
pci 0001:40:00.0: reg 10 32bit mmio: [0x000000-0x7fffffff]
PCI:0001:40:00.0 Resource 0 0000000000000000-000000007fffffff [21208] is unassigned
PCI: Hiding 4xx host bridge resources 0001:40:00.0
PCI: Fixup bus devices 64 (PHB)
pci_busdev_to_OF_node(64,0x0)
 parent is /plb/pciex@0c0000000
 result is <NULL>
PCI: Try to map irq for 0001:40:00.0...
pci_busdev_to_OF_node(64,0x0)
 parent is /plb/pciex@0c0000000
 result is <NULL>
pci 0001:41:00.0: reg 10 32bit mmio: [0x90000000-0x9001ffff]
PCI:0001:41:00.0 Resource 0 0000000090000000-000000009001ffff [20200] fixup...
PCI:0001:41:00.0            00000000a0000000-00000000a001ffff
pci 0001:41:00.0: PME# supported from D0 D3hot D3cold
pci 0001:41:00.0: PME# disabled
pci 0001:40:00.0: bridge io port: [0x00-0xfff]
pci 0001:40:00.0: bridge 32bit mmio: [0x90000000-0x94ffffff]
PCI:0001:40:00.0 Bus rsrc 0 0000000000000000-0000000000000fff [101] fixup...
PCI:0001:40:00.0            0000000000000000-0000000000000fff
PCI:0001:40:00.0 Bus rsrc 1 0000000090000000-0000000094ffffff [200] fixup...
PCI:0001:40:00.0            00000000a0000000-00000000a4ffffff
PCI: Fixup bus devices 65 (0001:40:00.0)
pci_busdev_to_OF_node(65,0x0)
PCI: Try to map irq for 0001:41:00.0...
pci_busdev_to_OF_node(65,0x0)
pci_busdev_to_OF_node(64,0x0)
 parent is /plb/pciex@0c0000000
 result is <NULL>
 Got one, spec 2 cells (0x0000000b 0x00000004...) on /interrupt-controller2
irq: irq 11 on host /interrupt-controller2 mapped to virtual irq 17
 Mapped to linux irq 17
pci 0001:42:01.0: PME# supported from D0 D3hot D3cold
pci 0001:42:01.0: PME# disabled
pci 0001:42:02.0: PME# supported from D0 D3hot D3cold
pci 0001:42:02.0: PME# disabled
pci 0001:41:00.0: bridge 32bit mmio: [0x90100000-0x94ffffff]
PCI:0001:41:00.0 Bus rsrc 1 0000000090100000-0000000094ffffff [200] fixup...
PCI:0001:41:00.0            00000000a0100000-00000000a4ffffff
PCI: Fixup bus devices 66 (0001:41:00.0)
pci_busdev_to_OF_node(66,0x8)
PCI: Try to map irq for 0001:42:01.0...
pci_busdev_to_OF_node(66,0x8)
pci_busdev_to_OF_node(65,0x0)
pci_busdev_to_OF_node(64,0x0)
 parent is /plb/pciex@0c0000000
 result is <NULL>
 Got one, spec 2 cells (0x0000000c 0x00000004...) on /interrupt-controller2
irq: irq 12 on host /interrupt-controller2 mapped to virtual irq 18
 Mapped to linux irq 18
pci_busdev_to_OF_node(66,0x10)
PCI: Try to map irq for 0001:42:02.0...
pci_busdev_to_OF_node(66,0x10)
pci_busdev_to_OF_node(65,0x0)
pci_busdev_to_OF_node(64,0x0)
 parent is /plb/pciex@0c0000000
 result is <NULL>
 Got one, spec 2 cells (0x0000000d 0x00000004...) on /interrupt-controller2
irq: irq 13 on host /interrupt-controller2 mapped to virtual irq 19
 Mapped to linux irq 19
pci 0001:43:00.0: reg 10 32bit mmio: [0x91000000-0x91ffffff]
pci 0001:43:00.0: reg 14 32bit mmio: [0x92000000-0x92ffffff]
PCI:0001:43:00.0 Resource 0 0000000091000000-0000000091ffffff [21208] fixup...
PCI:0001:43:00.0            00000000a1000000-00000000a1ffffff
PCI:0001:43:00.0 Resource 1 0000000092000000-0000000092ffffff [21208] fixup...
PCI:0001:43:00.0            00000000a2000000-00000000a2ffffff
pci 0001:42:01.0: bridge 32bit mmio: [0x90100000-0x92ffffff]
PCI:0001:42:01.0 Bus rsrc 1 0000000090100000-0000000092ffffff [200] fixup...
PCI:0001:42:01.0            00000000a0100000-00000000a2ffffff
PCI: Fixup bus devices 67 (0001:42:01.0)
pci_busdev_to_OF_node(67,0x0)
PCI: Try to map irq for 0001:43:00.0...
pci_busdev_to_OF_node(67,0x0)
pci_busdev_to_OF_node(66,0x8)
pci_busdev_to_OF_node(65,0x0)
pci_busdev_to_OF_node(64,0x0)
 parent is /plb/pciex@0c0000000
 result is <NULL>
 Got one, spec 2 cells (0x0000000c 0x00000004...) on /interrupt-controller2
 Mapped to linux irq 18
pci 0001:44:00.0: reg 10 32bit mmio: [0x93000000-0x93ffffff]
pci 0001:44:00.0: reg 14 32bit mmio: [0x94000000-0x94ffffff]
PCI:0001:44:00.0 Resource 0 0000000093000000-0000000093ffffff [21208] fixup...
PCI:0001:44:00.0            00000000a3000000-00000000a3ffffff
PCI:0001:44:00.0 Resource 1 0000000094000000-0000000094ffffff [21208] fixup...
PCI:0001:44:00.0            00000000a4000000-00000000a4ffffff
pci 0001:42:02.0: bridge 32bit mmio: [0x93000000-0x94ffffff]
PCI:0001:42:02.0 Bus rsrc 1 0000000093000000-0000000094ffffff [200] fixup...
PCI:0001:42:02.0            00000000a3000000-00000000a4ffffff
PCI: Fixup bus devices 68 (0001:42:02.0)
pci_busdev_to_OF_node(68,0x0)
PCI: Try to map irq for 0001:44:00.0...
pci_busdev_to_OF_node(68,0x0)
pci_busdev_to_OF_node(66,0x10)
pci_busdev_to_OF_node(65,0x0)
pci_busdev_to_OF_node(64,0x0)
 parent is /plb/pciex@0c0000000
 result is <NULL>
 Got one, spec 2 cells (0x0000000d 0x00000004...) on /interrupt-controller2
 Mapped to linux irq 19
PCI: Allocating bus resources for 0000:00...
PCI: PHB (bus 0) bridge rsrc 0: 00000000fffe0000-00000000fffeffff [0x100], parent c03de440 (PCI IO)
PCI: PHB (bus 0) bridge rsrc 1: 00000000e0000000-00000000e7ffffff [0x200], parent c03de424 (PCI mem)
PCI: Allocating bus resources for 0000:01...
PCI: Allocating bus resources for 0001:40...
PCI: PHB (bus 64) bridge rsrc 0: 0000000000000000-000000000000ffff [0x100], parent c03de440 (PCI IO)
PCI: PHB (bus 64) bridge rsrc 1: 0000000090000000-000000009fffffff [0x200], parent c03de424 (PCI mem)
PCI: Allocating bus resources for 0001:41...
PCI: Allocating bus resources for 0001:42...
PCI: Allocating bus resources for 0001:43...
PCI: Allocating bus resources for 0001:44...
Reserving legacy ranges for domain 0000
Candidate legacy IO: [0xfffe0000-0xfffe0fff]
hose mem offset: 0000000060000000
hose mem res: [0xe0000000-0xe7ffffff]
Reserving legacy ranges for domain 0001
Candidate legacy IO: [0x00-0xfff]
hose mem offset: 0000000010000000
hose mem res: [0x90000000-0x9fffffff]
PCI: Assigning unassigned resources...
pci 0000:00:00.0: PCI bridge, secondary bus 0000:01
pci 0000:00:00.0:   IO window: disabled
pci 0000:00:00.0:   MEM window: 0x80000000-0x85ffffff
pci 0000:00:00.0:   PREFETCH window: disabled
pci 0001:42:01.0: PCI bridge, secondary bus 0001:43
pci 0001:42:01.0:   IO window: disabled
pci 0001:42:01.0:   MEM window: disabled
pci 0001:42:01.0:   PREFETCH window: 0x00000080000000-0x00000081ffffff
pci 0001:42:02.0: PCI bridge, secondary bus 0001:44
pci 0001:42:02.0:   IO window: disabled
pci 0001:42:02.0:   MEM window: disabled
pci 0001:42:02.0:   PREFETCH window: 0x00000082000000-0x00000083ffffff
pci 0001:41:00.0: PCI bridge, secondary bus 0001:42
pci 0001:41:00.0:   IO window: disabled
pci 0001:41:00.0:   MEM window: disabled
pci 0001:41:00.0:   PREFETCH window: 0x00000080000000-0x00000083ffffff
pci 0001:40:00.0: PCI bridge, secondary bus 0001:41
pci 0001:40:00.0:   IO window: disabled
pci 0001:40:00.0:   MEM window: 0x84000000-0x840fffff
pci 0001:40:00.0:   PREFETCH window: 0x00000080000000-0x00000083ffffff
pci_bus 0000:00: resource 0 io:  [0xfffe0000-0xfffeffff]
pci_bus 0000:00: resource 1 mem: [0xe0000000-0xe7ffffff]
pci_bus 0000:01: resource 0 mem: [0xfffe0000-0xfffe0fff]
pci_bus 0000:01: resource 1 mem: [0xe0000000-0xe5ffffff]
pci_bus 0001:40: resource 0 io:  [0x00-0xffff]
pci_bus 0001:40: resource 1 mem: [0x90000000-0x9fffffff]
pci_bus 0001:41: resource 0 mem: [0x0-0xfff]
pci_bus 0001:41: resource 1 mem: [0x94000000-0x940fffff]
pci_bus 0001:41: resource 2 pref mem [0x90000000-0x93ffffff]
pci_bus 0001:42: resource 1 mem: [0xa0100000-0xa4ffffff]
pci_bus 0001:42: resource 2 pref mem [0x90000000-0x93ffffff]
pci_bus 0001:43: resource 1 mem: [0xa0100000-0xa2ffffff]
pci_bus 0001:43: resource 2 pref mem [0x90000000-0x91ffffff]
pci_bus 0001:44: resource 1 mem: [0xa3000000-0xa4ffffff]
pci_bus 0001:44: resource 2 pref mem [0x92000000-0x93ffffff]
bio: create slab <bio-0> at 0
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
Switched to high resolution mode on CPU 0
NET: Registered protocol family 2
IP route cache hash table entries: 2048 (order: 1, 8192 bytes)
TCP established hash table entries: 8192 (order: 4, 65536 bytes)
TCP bind hash table entries: 8192 (order: 3, 32768 bytes)
TCP: Hash tables configured (established 8192 bind 8192)
TCP reno registered
NET: Registered protocol family 1
Trying to unpack rootfs image as initramfs...
Freeing initrd memory: 3078k freed
irq: irq 26 on host /interrupt-controller mapped to virtual irq 26
irq: irq 1 on host /interrupt-controller mapped to virtual irq 20
irq: irq 30 on host /interrupt-controller2 mapped to virtual irq 21
irq: irq 26 on host /interrupt-controller1 mapped to virtual irq 22
irq: irq 12 on host /interrupt-controller mapped to virtual irq 23
I-pipe: Domain Xenomai registered.
Xenomai: hal/powerpc started.
Xenomai: real-time nucleus v2.4.10 (Flavor Crystal 7) loaded.
Xenomai: starting native API services.
Xenomai: starting POSIX services.
Xenomai: starting RTDM services.
Installing knfsd (copyright (C) 1996 okir@monad.swb.de).
fuse init (API version 7.11)
msgmni has been set to 498
alg: No test for stdrng (krng)
io scheduler noop registered
io scheduler anticipatory registered (default)
io scheduler deadline registered
io scheduler cfq registered
aer 0001:41:00.0:pcie12: service driver aer loaded
aer 0001:42:01.0:pcie22: service driver aer loaded
aer 0001:42:02.0:pcie22: service driver aer loaded
pci_hotplug: PCI Hot Plug PCI Core version: 0.5
Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
serial8250.0: ttyS0 at MMIO 0xef600200 (irq = 26) is a 16550A
serial8250.0: ttyS1 at MMIO 0xef600300 (irq = 20) is a 16550A
console [ttyS1] enabled
ef600200.serial: ttyS0 at MMIO 0xef600200 (irq = 26) is a 16550A
ef600300.serial: ttyS1 at MMIO 0xef600300 (irq = 20) is a 16550A
brd: module loaded
Driver 'sd' needs updating - please use bus_type methods
PPC 4xx OCP EMAC driver, version 3.54
irq: irq 10 on host /interrupt-controller mapped to virtual irq 24
irq: irq 11 on host /interrupt-controller mapped to virtual irq 25
irq: irq 0 on host /interrupt-controller1 mapped to virtual irq 27
irq: irq 1 on host /interrupt-controller1 mapped to virtual irq 29
irq: irq 2 on host /interrupt-controller1 mapped to virtual irq 31
MAL v2 /plb/mcmal, 2 TX channels, 2 RX channels
RGMII /plb/opb/emac-rgmii@ef600b00 initialized with MDIO support
irq: irq 24 on host /interrupt-controller mapped to virtual irq 32
irq: irq 29 on host /interrupt-controller1 mapped to virtual irq 33
/plb/opb/emac-rgmii@ef600b00: input 0 in RGMII mode
eth0: EMAC-0 /plb/opb/ethernet@ef600900, MAC 00:90:f9:10:1a:08
eth0: found Marvell 88E1111 Ethernet PHY (0x04)
irq: irq 25 on host /interrupt-controller mapped to virtual irq 34
irq: irq 31 on host /interrupt-controller1 mapped to virtual irq 35
/plb/opb/emac-rgmii@ef600b00: input 1 in RGMII mode
eth1: EMAC-1 /plb/opb/ethernet@ef600a00, MAC 00:90:f9:10:1a:09
eth1: found Marvell 88E1111 Ethernet PHY (0x05)
fc000000.nor_flash: Found 1 x16 devices at 0x0 in 16-bit bank
 Intel/Sharp Extended Query Table at 0x010A
 Intel/Sharp Extended Query Table at 0x010A
 Intel/Sharp Extended Query Table at 0x010A
 Intel/Sharp Extended Query Table at 0x010A
 Intel/Sharp Extended Query Table at 0x010A
Using buffer write method
Using auto-unlock on power-up/resume
cfi_cmdset_0001: Erase suspend on write enabled
erase region 0: offset=0x0,size=0x8000,blocks=4
erase region 1: offset=0x20000,size=0x20000,blocks=511
RedBoot partition parsing not available
Creating 7 MTD partitions on "fc000000.nor_flash":
0x000000000000-0x000000800000 : "kernel0"
0x000000800000-0x000001000000 : "kernel1"
0x000001000000-0x000001800000 : "kernel2"
0x000001800000-0x000003f40000 : "install"
0x000003f40000-0x000003f60000 : "env0"
0x000003f60000-0x000003f80000 : "env1"
0x000003f80000-0x000004000000 : "u-boot"
irq: irq 8 on host /interrupt-controller mapped to virtual irq 36
spi_ppc4xx_of ef600600.spi: driver initialized
Initializing USB Mass Storage driver...
usbcore: registered new interface driver usb-storage
USB Mass Storage support registered.
dwc_otg: version 2.60a 22-NOV-2006
dwc_otg: Shared Tx FIFO mode
dwc_otg: Using DMA mode
dwc_otg dwc_otg.0: DWC OTG Controller
dwc_otg dwc_otg.0: new USB bus registered, assigned bus number 1
dwc_otg dwc_otg.0: irq 21, io mem 0x00000000
dwc_otg: Init: Port Power? op_state=1
dwc_otg: Init: Power Port (0)
usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
usb usb1: Product: DWC OTG Controller
usb usb1: Manufacturer: Linux 2.6.30.3-00063-g0af2edc-dirty dwc_otg_hcd
usb usb1: SerialNumber: dwc_otg.0
usb usb1: configuration #1 chosen from 1 choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 1 port detected
i2c /dev entries driver
irq: irq 2 on host /interrupt-controller mapped to virtual irq 37
ibm-iic ef600400.i2c: using standard (100 kHz) mode
irq: irq 7 on host /interrupt-controller mapped to virtual irq 38
ibm-iic ef600500.i2c: using standard (100 kHz) mode
lm75: probe of 0-0048 failed with error -121
hwmon-vid: Unknown VRM version of your CPU
PowerPC Book-E Watchdog Timer Loaded
TCP cubic registered
Initializing XFRM netlink socket
NET: Registered protocol family 17
NET: Registered protocol family 15
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
802.1Q VLAN Support v1.8 Ben Greear <greearb@candelatech.com>
All bugs added by David S. Miller <davem@redhat.com>
usb 1-1: new high speed USB device using dwc_otg and address 2
usb 1-1: New USB device found, idVendor=0634, idProduct=0655
usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 1-1: Product: Real SSD eUSB 2GB
usb 1-1: Manufacturer: Micron Technology
usb 1-1: SerialNumber: 4BF0022700035321
usb 1-1: configuration #1 chosen from 1 choice
scsi0 : SCSI emulation for USB Mass Storage devices
usb-storage: device found at 2
usb-storage: waiting for device to settle before scanning
eth0: link is down
eth0: link is up, 100 HDX
IP-Config: Complete:
     device=eth0, addr=137.237.178.150, mask=255.255.255.0, gw=137.237.178.1,
     host=flx-am, domain=, nis-domain=(none),
     bootserver=137.237.178.9, rootserver=137.237.178.9, rootpath=
Freeing unused kernel memory: 164k init
at24 0-0050: 512 byte 24c04 EEPROM (writable)
at24 0-0052: 512 byte 24c04 EEPROM (writable)
scsi 0:0:0:0: Direct-Access     MICRON   eUSB DISK        1110 PQ: 0 ANSI: 0 CCS
sd 0:0:0:0: Attached scsi generic sg0 type 0
usb-storage: device scan complete
sd 0:0:0:0: [sda] 3964928 512-byte hardware sectors: (2.03 GB/1.89 GiB)
sd 0:0:0:0: [sda] Write Protect is off
sd 0:0:0:0: [sda] Mode Sense: 43 00 00 00
sd 0:0:0:0: [sda] Assuming drive cache: write through
sd 0:0:0:0: [sda] Assuming drive cache: write through
 sda: sda1 sda2 sda3 sda4
sd 0:0:0:0: [sda] Attached SCSI disk
kjournald starting.  Commit interval 5 seconds
EXT3 FS on sda2, internal journal
EXT3-fs: mounted filesystem with journal data mode.
kjournald starting.  Commit interval 5 seconds
EXT3 FS on sda1, internal journal
EXT3-fs: mounted filesystem with journal data mode.
kjournald starting.  Commit interval 5 seconds
EXT3 FS on sda3, internal journal
EXT3-fs: mounted filesystem with journal data mode.
kjournald starting.  Commit interval 5 seconds
EXT3 FS on sda4, internal journal
EXT3-fs: mounted filesystem with journal data mode.
at24 0-0050: 512 byte 24c04 EEPROM (writable)
at24 0-0052: 512 byte 24c04 EEPROM (writable)
dx83xx 0001:43:00.0: device not available because of BAR 0 [0xa1000000-0xa1ffffff] collisions
dx83xx: probe of 0001:43:00.0 failed with error -22
dx83xx 0001:44:00.0: device not available because of BAR 0 [0xa3000000-0xa3ffffff] collisions
dx83xx: probe of 0001:44:00.0 failed with error -22

^ permalink raw reply

* Re: [PATCH 11/14] PM / AVR32: Use struct syscore_ops instead of sysdevs for PM
From: Rafael J. Wysocki @ 2011-04-26 17:14 UTC (permalink / raw)
  To: Hans-Christian Egtvedt
  Cc: Kevin Hilman, Guan Xuetao, Russell King, Konrad Rzeszutek Wilk,
	Greg KH, LKML, Ralf Baechle, Jeremy Fitzhardinge, Ben Dooks,
	Jiri Kosina, Kay Sievers, Mike Frysinger, Linux PM mailing list,
	linux-omap, linuxppc-dev, linux-arm-kernel
In-Reply-To: <1303820532.3125.12.camel@hcegtvedt>

On Tuesday, April 26, 2011, Hans-Christian Egtvedt wrote:
> On Sun, 2011-04-17 at 23:13 +0200, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rjw@sisk.pl>
> > 
> > Convert some AVR32 architecture's code to using struct syscore_ops
> > objects for power management instead of sysdev classes and sysdevs.
> > 
> > This simplifies the code and reduces the kernel's memory footprint.
> > It also is necessary for removing sysdevs from the kernel entirely in
> > the future.
> > 
> > Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
> 
> Acked-by: Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>
> 
> Thanks, nice work. Tested and run on hardware.

Thanks!

Rafael

^ permalink raw reply

* Re: [PATCH] powerpc/kexec: Fix build failure on 32-bit SMP
From: Paul Gortmaker @ 2011-04-26 18:25 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: linuxppc-dev
In-Reply-To: <1303693471.3032.212.camel@localhost>

On 11-04-24 09:04 PM, Ben Hutchings wrote:
> Commit b987812b3fcaf70fdf0037589e5d2f5f2453e6ce left
> crash_kexec_wait_realmode() undefined for UP.
> 
> Commit 7c7a81b53e581d727d069cc45df5510516faac31 defined it for UP but
> left it undefined for 32-bit SMP.

Crap,  I'd originally tested it for 32-SMP too, but not retested after
fixing the UP regression.  I'm resolving to not touch this file again. :)

> 
> Seems like people are getting confused by nested #ifdef's, so move the

So true.

> definitions of crash_kexec_wait_realmode() after the #ifdef CONFIG_SMP
> section.

I probably should have done this from the get-go as well.  Oh well.
At least we are progressing towards a more readable file.

> 
> Compile-tested with 32-bit UP, 32-bit SMP and 64-bit SMP configurations.

Since it seems I always get bit by the one combo I skip testing on,
I also tested 64-bit UP as well - just to be extra sure.  Thanks for
fixing my brown paper bag moment.

> 
> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>

Tested-by: Paul Gortmaker <paul.gortmaker@windriver.com>

Paul.

> ---
> --- a/arch/powerpc/kernel/crash.c
> +++ b/arch/powerpc/kernel/crash.c
> @@ -162,34 +162,6 @@
>  	/* Leave the IPI callback set */
>  }
>  
> -/* wait for all the CPUs to hit real mode but timeout if they don't come in */
> -#ifdef CONFIG_PPC_STD_MMU_64
> -static void crash_kexec_wait_realmode(int cpu)
> -{
> -	unsigned int msecs;
> -	int i;
> -
> -	msecs = 10000;
> -	for (i=0; i < NR_CPUS && msecs > 0; i++) {
> -		if (i == cpu)
> -			continue;
> -
> -		while (paca[i].kexec_state < KEXEC_STATE_REAL_MODE) {
> -			barrier();
> -			if (!cpu_possible(i)) {
> -				break;
> -			}
> -			if (!cpu_online(i)) {
> -				break;
> -			}
> -			msecs--;
> -			mdelay(1);
> -		}
> -	}
> -	mb();
> -}
> -#endif	/* CONFIG_PPC_STD_MMU_64 */
> -
>  /*
>   * This function will be called by secondary cpus or by kexec cpu
>   * if soft-reset is activated to stop some CPUs.
> @@ -234,7 +206,6 @@
>  }
>  
>  #else	/* ! CONFIG_SMP */
> -static inline void crash_kexec_wait_realmode(int cpu) {}
>  
>  static void crash_kexec_prepare_cpus(int cpu)
>  {
> @@ -257,6 +228,36 @@
>  }
>  #endif	/* CONFIG_SMP */
>  
> +/* wait for all the CPUs to hit real mode but timeout if they don't come in */
> +#if defined(CONFIG_SMP) && defined(CONFIG_PPC_STD_MMU_64)
> +static void crash_kexec_wait_realmode(int cpu)
> +{
> +	unsigned int msecs;
> +	int i;
> +
> +	msecs = 10000;
> +	for (i=0; i < NR_CPUS && msecs > 0; i++) {
> +		if (i == cpu)
> +			continue;
> +
> +		while (paca[i].kexec_state < KEXEC_STATE_REAL_MODE) {
> +			barrier();
> +			if (!cpu_possible(i)) {
> +				break;
> +			}
> +			if (!cpu_online(i)) {
> +				break;
> +			}
> +			msecs--;
> +			mdelay(1);
> +		}
> +	}
> +	mb();
> +}
> +#else
> +static inline void crash_kexec_wait_realmode(int cpu) {}
> +#endif	/* CONFIG_SMP && CONFIG_PPC_STD_MMU_64 */
> +
>  /*
>   * Register a function to be called on shutdown.  Only use this if you
>   * can't reset your device in the second kernel.
> 

^ permalink raw reply

* Re: device not available because of BAR 0 collisions
From: Benjamin Herrenschmidt @ 2011-04-26 23:39 UTC (permalink / raw)
  To: Steven A. Falco; +Cc: linuxppc-dev
In-Reply-To: <4DB6CAD0.5030102@harris.com>

On Tue, 2011-04-26 at 09:38 -0400, Steven A. Falco wrote:
> On 04/25/2011 08:01 PM, Benjamin Herrenschmidt wrote:
> > On Mon, 2011-04-25 at 16:10 -0400, Steven A. Falco wrote:
> >> I'm getting an error message when trying to talk to some custom
> >> hardware:
> >>
> >> dx83xx 0001:43:00.0: device not available because of BAR 0
> >> [0xa1000000-0xa1ffffff] collisions
> >>
> >> I see in setup-res.c that this message comes out when there is no
> >> parent for
> >> a device resource.
> > 
> >  .../...
> > 
> > It mostly happens in arch/powerpc/kernel/pci-common.c and the generic
> > setup-res.c
> > 
> > Try #define DEBUG at the top (before the #includes) of pci-common.c and
> > pci_32.c (remove the exiting #undef in the last one) and send us the
> > full dmesg log, along with the output of cat /proc/iomem

Have you set any specific flags ? IE. Modified the value of
ppc_pci_flags from what the 4xx code sets originally ?

It does look to me like some of your device BARs have been setup already
by the firmware in a way that conflict with the way you configure your
ranges, and the kernel doesn't appear to detect nor try to remap that
which would happen if you have the "probe only" flag set.

IE. On your c0000000 bus, you have memory at 90000000 CPU space mapped
to 80000000 PCI space. However, when probing, the kernel finds:

pci 0001:41:00.0: reg 10 32bit mmio: [0x90000000-0x9001ffff]

IE. A BAR was already set with a value of 90000000 PCI-side which is out
of the bounds you have for your bus.

Maybe you really want to configure that second bus to have CPU 90000000
mapped to 90000000 PCI-side ? (IE. a 1:1 mapping). That would be
something to fix in your "ranges" property.

Cheers,
Ben.

> > Cheers,
> > Ben.
> > 
> > 
> > 
> 
> Thanks for the help!
> 
> PCIe 0 has an FPGA connected - it is behaving as expected.  PCIe 1 has the
> PLX PCIe switch followed by a pair of ASICs - they are the ones generating
> the error.
> 
> Here is /proc/iomem:
> 
> 90000000-9fffffff : /plb/pciex@0c0000000
>   90000000-93ffffff : PCI Bus 0001:41
>     90000000-93ffffff : PCI Bus 0001:42
>       90000000-91ffffff : PCI Bus 0001:43
>       92000000-93ffffff : PCI Bus 0001:44
>   94000000-940fffff : PCI Bus 0001:41
>     94000000-9401ffff : 0001:41:00.0
> e0000000-e7ffffff : /plb/pciex@0a0000000
>   e0000000-e5ffffff : PCI Bus 0000:01
>     e0000000-e3ffffff : 0000:01:00.0
>     e4000000-e40fffff : 0000:01:00.0
>     e4100000-e41fffff : 0000:01:00.0
> ef600200-ef600207 : serial
> ef600300-ef600307 : serial
> ef600600-ef600606 : spi_ppc4xx_of
> ef6c0000-ef6cffff : dwc_otg.0
>   ef6c0000-ef6cffff : dwc_otg
> fc000000-ffffffff : fc000000.nor_flash
> 
> And here is dmesg, captured after the failed modprobe, so you can see
> those error messages (DEBUG enabled in pci-common.c and pci_32.c):
> 
> Using Flex-AM machine description
> Linux version 2.6.30.3-00063-g0af2edc-dirty (sfalco@hw1.cs.myharris.net) (gcc version 4.2.2) #35 Tue Apr 26 09:20:23 EDT 2011
> Found initrd at 0xcfba0000:0xcfea1872
> Found legacy serial port 0 for /plb/opb/serial@ef600200
>   mem=ef600200, taddr=ef600200, irq=0, clk=33333333, speed=0
> Found legacy serial port 1 for /plb/opb/serial@ef600300
>   mem=ef600300, taddr=ef600300, irq=0, clk=33333333, speed=0
> Top of RAM: 0x10000000, Total RAM: 0x10000000
> Memory hole size: 0MB
> Zone PFN ranges:
>   DMA      0x00000000 -> 0x00010000
>   Normal   0x00010000 -> 0x00010000
> Movable zone start PFN for each node
> early_node_map[1] active PFN ranges
>     0: 0x00000000 -> 0x00010000
> On node 0 totalpages: 65536
> free_area_init_node: node 0, pgdat c0406bdc, node_mem_map c0443000
>   DMA zone: 512 pages used for memmap
>   DMA zone: 0 pages reserved
>   DMA zone: 65024 pages, LIFO batch:15
> MMU: Allocated 1088 bytes of context maps for 255 contexts
> Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 65024
> Kernel command line: root=/dev/sda2 rw ip=137.237.178.150:137.237.178.9:137.237.178.1:255.255.255.0:flx-am:eth0:off panic=1 console=ttyS1,115200 debug
> NR_IRQS:512
> UIC0 (32 IRQ sources) at DCR 0xc0
> UIC1 (32 IRQ sources) at DCR 0xd0
> irq: irq 30 on host /interrupt-controller mapped to virtual irq 30
> UIC2 (32 IRQ sources) at DCR 0xe0
> irq: irq 28 on host /interrupt-controller mapped to virtual irq 28
> PID hash table entries: 1024 (order: 10, 4096 bytes)
> time_init: decrementer frequency = 400.000000 MHz
> time_init: processor frequency   = 400.000000 MHz
> clocksource: timebase mult[a00000] shift[22] registered
> clockevent: decrementer mult[6666] shift[16] cpu[0]
> I-pipe 2.7-02: pipeline enabled.
> Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
> Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
> Memory: 252092k/262144k available (3944k kernel code, 9744k reserved, 184k data, 204k bss, 164k init)
> Kernel virtual memory layout:
>   * 0xffffe000..0xfffff000  : fixmap
>   * 0xfde00000..0xfe000000  : consistent mem
>   * 0xfde00000..0xfde00000  : early ioremap
>   * 0xd1000000..0xfde00000  : vmalloc & ioremap
> SLUB: Genslabs=11, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
> Calibrating delay loop... 798.72 BogoMIPS (lpj=1597440)
> Mount-cache hash table entries: 512
> net_namespace: 520 bytes
> NET: Registered protocol family 16
> PCIE0: Checking link...
> PCIE0: Device detected, waiting for link...
> PCIE0: link is up !
> PCI host bridge /plb/pciex@0a0000000 (primary) ranges:
>  MEM 0x00000000e0000000..0x00000000e7ffffff -> 0x0000000080000000
>   IO 0x00000000e8000000..0x00000000e800ffff -> 0x0000000000000000
> 4xx PCI DMA offset set to 0x00000000
> PCIE0: successfully set as root-complex
> PCIE1: Checking link...
> PCIE1: Device detected, waiting for link...
> PCIE1: link is up !
> PCI host bridge /plb/pciex@0c0000000 (primary) ranges:
>  MEM 0x0000000090000000..0x000000009fffffff -> 0x0000000080000000
>   IO 0x00000000e8010000..0x00000000e801ffff -> 0x0000000000000000
> 4xx PCI DMA offset set to 0x00000000
> PCIE1: successfully set as root-complex
> PCI: Probing PCI hardware
> PCI: Scanning PHB /plb/pciex@0a0000000
> PCI: PHB IO resource    = 00000000fffe0000-00000000fffeffff [100]
> PCI: PHB MEM resource 0 = 00000000e0000000-00000000e7ffffff [200]
> PCI: PHB MEM offset     = 0000000060000000
> PCI: PHB IO  offset     = fffe0000
> pci 0000:00:00.0: reg 10 32bit mmio: [0x000000-0x7fffffff]
> PCI:0000:00:00.0 Resource 0 0000000000000000-000000007fffffff [21208] is unassigned
> PCI: Hiding 4xx host bridge resources 0000:00:00.0
> PCI: Fixup bus devices 0 (PHB)
> pci_busdev_to_OF_node(0,0x0)
>  parent is /plb/pciex@0a0000000
>  result is <NULL>
> PCI: Try to map irq for 0000:00:00.0...
> pci_busdev_to_OF_node(0,0x0)
>  parent is /plb/pciex@0a0000000
>  result is <NULL>
> pci 0000:01:00.0: reg 10 32bit mmio: [0x80000000-0x800fffff]
> pci 0000:01:00.0: reg 14 32bit mmio: [0x80100000-0x801fffff]
> pci 0000:01:00.0: reg 18 32bit mmio: [0x84000000-0x87ffffff]
> PCI:0000:01:00.0 Resource 0 0000000080000000-00000000800fffff [20200] fixup...
> PCI:0000:01:00.0            00000000e0000000-00000000e00fffff
> PCI:0000:01:00.0 Resource 1 0000000080100000-00000000801fffff [20200] fixup...
> PCI:0000:01:00.0            00000000e0100000-00000000e01fffff
> PCI:0000:01:00.0 Resource 2 0000000084000000-0000000087ffffff [20200] fixup...
> PCI:0000:01:00.0            00000000e4000000-00000000e7ffffff
> pci 0000:00:00.0: bridge io port: [0x00-0xfff]
> pci 0000:00:00.0: bridge 32bit mmio: [0x80000000-0x87ffffff]
> PCI:0000:00:00.0 Bus rsrc 0 0000000000000000-0000000000000fff [101] fixup...
> PCI:0000:00:00.0            00000000fffe0000-00000000fffe0fff
> PCI:0000:00:00.0 Bus rsrc 1 0000000080000000-0000000087ffffff [200] fixup...
> PCI:0000:00:00.0            00000000e0000000-00000000e7ffffff
> PCI: Fixup bus devices 1 (0000:00:00.0)
> pci_busdev_to_OF_node(1,0x0)
> PCI: Try to map irq for 0000:01:00.0...
> pci_busdev_to_OF_node(1,0x0)
> pci_busdev_to_OF_node(0,0x0)
>  parent is /plb/pciex@0a0000000
>  result is <NULL>
>  Got one, spec 2 cells (0x00000000 0x00000004...) on /interrupt-controller2
> irq: irq 0 on host /interrupt-controller2 mapped to virtual irq 16
>  Mapped to linux irq 16
> PCI: Scanning PHB /plb/pciex@0c0000000
> PCI: PHB IO resource    = 0000000000000000-000000000000ffff [100]
> PCI: PHB MEM resource 0 = 0000000090000000-000000009fffffff [200]
> PCI: PHB MEM offset     = 0000000010000000
> PCI: PHB IO  offset     = 00000000
> pci 0001:40:00.0: reg 10 32bit mmio: [0x000000-0x7fffffff]
> PCI:0001:40:00.0 Resource 0 0000000000000000-000000007fffffff [21208] is unassigned
> PCI: Hiding 4xx host bridge resources 0001:40:00.0
> PCI: Fixup bus devices 64 (PHB)
> pci_busdev_to_OF_node(64,0x0)
>  parent is /plb/pciex@0c0000000
>  result is <NULL>
> PCI: Try to map irq for 0001:40:00.0...
> pci_busdev_to_OF_node(64,0x0)
>  parent is /plb/pciex@0c0000000
>  result is <NULL>
> pci 0001:41:00.0: reg 10 32bit mmio: [0x90000000-0x9001ffff]
> PCI:0001:41:00.0 Resource 0 0000000090000000-000000009001ffff [20200] fixup...
> PCI:0001:41:00.0            00000000a0000000-00000000a001ffff
> pci 0001:41:00.0: PME# supported from D0 D3hot D3cold
> pci 0001:41:00.0: PME# disabled
> pci 0001:40:00.0: bridge io port: [0x00-0xfff]
> pci 0001:40:00.0: bridge 32bit mmio: [0x90000000-0x94ffffff]
> PCI:0001:40:00.0 Bus rsrc 0 0000000000000000-0000000000000fff [101] fixup...
> PCI:0001:40:00.0            0000000000000000-0000000000000fff
> PCI:0001:40:00.0 Bus rsrc 1 0000000090000000-0000000094ffffff [200] fixup...
> PCI:0001:40:00.0            00000000a0000000-00000000a4ffffff
> PCI: Fixup bus devices 65 (0001:40:00.0)
> pci_busdev_to_OF_node(65,0x0)
> PCI: Try to map irq for 0001:41:00.0...
> pci_busdev_to_OF_node(65,0x0)
> pci_busdev_to_OF_node(64,0x0)
>  parent is /plb/pciex@0c0000000
>  result is <NULL>
>  Got one, spec 2 cells (0x0000000b 0x00000004...) on /interrupt-controller2
> irq: irq 11 on host /interrupt-controller2 mapped to virtual irq 17
>  Mapped to linux irq 17
> pci 0001:42:01.0: PME# supported from D0 D3hot D3cold
> pci 0001:42:01.0: PME# disabled
> pci 0001:42:02.0: PME# supported from D0 D3hot D3cold
> pci 0001:42:02.0: PME# disabled
> pci 0001:41:00.0: bridge 32bit mmio: [0x90100000-0x94ffffff]
> PCI:0001:41:00.0 Bus rsrc 1 0000000090100000-0000000094ffffff [200] fixup...
> PCI:0001:41:00.0            00000000a0100000-00000000a4ffffff
> PCI: Fixup bus devices 66 (0001:41:00.0)
> pci_busdev_to_OF_node(66,0x8)
> PCI: Try to map irq for 0001:42:01.0...
> pci_busdev_to_OF_node(66,0x8)
> pci_busdev_to_OF_node(65,0x0)
> pci_busdev_to_OF_node(64,0x0)
>  parent is /plb/pciex@0c0000000
>  result is <NULL>
>  Got one, spec 2 cells (0x0000000c 0x00000004...) on /interrupt-controller2
> irq: irq 12 on host /interrupt-controller2 mapped to virtual irq 18
>  Mapped to linux irq 18
> pci_busdev_to_OF_node(66,0x10)
> PCI: Try to map irq for 0001:42:02.0...
> pci_busdev_to_OF_node(66,0x10)
> pci_busdev_to_OF_node(65,0x0)
> pci_busdev_to_OF_node(64,0x0)
>  parent is /plb/pciex@0c0000000
>  result is <NULL>
>  Got one, spec 2 cells (0x0000000d 0x00000004...) on /interrupt-controller2
> irq: irq 13 on host /interrupt-controller2 mapped to virtual irq 19
>  Mapped to linux irq 19
> pci 0001:43:00.0: reg 10 32bit mmio: [0x91000000-0x91ffffff]
> pci 0001:43:00.0: reg 14 32bit mmio: [0x92000000-0x92ffffff]
> PCI:0001:43:00.0 Resource 0 0000000091000000-0000000091ffffff [21208] fixup...
> PCI:0001:43:00.0            00000000a1000000-00000000a1ffffff
> PCI:0001:43:00.0 Resource 1 0000000092000000-0000000092ffffff [21208] fixup...
> PCI:0001:43:00.0            00000000a2000000-00000000a2ffffff
> pci 0001:42:01.0: bridge 32bit mmio: [0x90100000-0x92ffffff]
> PCI:0001:42:01.0 Bus rsrc 1 0000000090100000-0000000092ffffff [200] fixup...
> PCI:0001:42:01.0            00000000a0100000-00000000a2ffffff
> PCI: Fixup bus devices 67 (0001:42:01.0)
> pci_busdev_to_OF_node(67,0x0)
> PCI: Try to map irq for 0001:43:00.0...
> pci_busdev_to_OF_node(67,0x0)
> pci_busdev_to_OF_node(66,0x8)
> pci_busdev_to_OF_node(65,0x0)
> pci_busdev_to_OF_node(64,0x0)
>  parent is /plb/pciex@0c0000000
>  result is <NULL>
>  Got one, spec 2 cells (0x0000000c 0x00000004...) on /interrupt-controller2
>  Mapped to linux irq 18
> pci 0001:44:00.0: reg 10 32bit mmio: [0x93000000-0x93ffffff]
> pci 0001:44:00.0: reg 14 32bit mmio: [0x94000000-0x94ffffff]
> PCI:0001:44:00.0 Resource 0 0000000093000000-0000000093ffffff [21208] fixup...
> PCI:0001:44:00.0            00000000a3000000-00000000a3ffffff
> PCI:0001:44:00.0 Resource 1 0000000094000000-0000000094ffffff [21208] fixup...
> PCI:0001:44:00.0            00000000a4000000-00000000a4ffffff
> pci 0001:42:02.0: bridge 32bit mmio: [0x93000000-0x94ffffff]
> PCI:0001:42:02.0 Bus rsrc 1 0000000093000000-0000000094ffffff [200] fixup...
> PCI:0001:42:02.0            00000000a3000000-00000000a4ffffff
> PCI: Fixup bus devices 68 (0001:42:02.0)
> pci_busdev_to_OF_node(68,0x0)
> PCI: Try to map irq for 0001:44:00.0...
> pci_busdev_to_OF_node(68,0x0)
> pci_busdev_to_OF_node(66,0x10)
> pci_busdev_to_OF_node(65,0x0)
> pci_busdev_to_OF_node(64,0x0)
>  parent is /plb/pciex@0c0000000
>  result is <NULL>
>  Got one, spec 2 cells (0x0000000d 0x00000004...) on /interrupt-controller2
>  Mapped to linux irq 19
> PCI: Allocating bus resources for 0000:00...
> PCI: PHB (bus 0) bridge rsrc 0: 00000000fffe0000-00000000fffeffff [0x100], parent c03de440 (PCI IO)
> PCI: PHB (bus 0) bridge rsrc 1: 00000000e0000000-00000000e7ffffff [0x200], parent c03de424 (PCI mem)
> PCI: Allocating bus resources for 0000:01...
> PCI: Allocating bus resources for 0001:40...
> PCI: PHB (bus 64) bridge rsrc 0: 0000000000000000-000000000000ffff [0x100], parent c03de440 (PCI IO)
> PCI: PHB (bus 64) bridge rsrc 1: 0000000090000000-000000009fffffff [0x200], parent c03de424 (PCI mem)
> PCI: Allocating bus resources for 0001:41...
> PCI: Allocating bus resources for 0001:42...
> PCI: Allocating bus resources for 0001:43...
> PCI: Allocating bus resources for 0001:44...
> Reserving legacy ranges for domain 0000
> Candidate legacy IO: [0xfffe0000-0xfffe0fff]
> hose mem offset: 0000000060000000
> hose mem res: [0xe0000000-0xe7ffffff]
> Reserving legacy ranges for domain 0001
> Candidate legacy IO: [0x00-0xfff]
> hose mem offset: 0000000010000000
> hose mem res: [0x90000000-0x9fffffff]
> PCI: Assigning unassigned resources...
> pci 0000:00:00.0: PCI bridge, secondary bus 0000:01
> pci 0000:00:00.0:   IO window: disabled
> pci 0000:00:00.0:   MEM window: 0x80000000-0x85ffffff
> pci 0000:00:00.0:   PREFETCH window: disabled
> pci 0001:42:01.0: PCI bridge, secondary bus 0001:43
> pci 0001:42:01.0:   IO window: disabled
> pci 0001:42:01.0:   MEM window: disabled
> pci 0001:42:01.0:   PREFETCH window: 0x00000080000000-0x00000081ffffff
> pci 0001:42:02.0: PCI bridge, secondary bus 0001:44
> pci 0001:42:02.0:   IO window: disabled
> pci 0001:42:02.0:   MEM window: disabled
> pci 0001:42:02.0:   PREFETCH window: 0x00000082000000-0x00000083ffffff
> pci 0001:41:00.0: PCI bridge, secondary bus 0001:42
> pci 0001:41:00.0:   IO window: disabled
> pci 0001:41:00.0:   MEM window: disabled
> pci 0001:41:00.0:   PREFETCH window: 0x00000080000000-0x00000083ffffff
> pci 0001:40:00.0: PCI bridge, secondary bus 0001:41
> pci 0001:40:00.0:   IO window: disabled
> pci 0001:40:00.0:   MEM window: 0x84000000-0x840fffff
> pci 0001:40:00.0:   PREFETCH window: 0x00000080000000-0x00000083ffffff
> pci_bus 0000:00: resource 0 io:  [0xfffe0000-0xfffeffff]
> pci_bus 0000:00: resource 1 mem: [0xe0000000-0xe7ffffff]
> pci_bus 0000:01: resource 0 mem: [0xfffe0000-0xfffe0fff]
> pci_bus 0000:01: resource 1 mem: [0xe0000000-0xe5ffffff]
> pci_bus 0001:40: resource 0 io:  [0x00-0xffff]
> pci_bus 0001:40: resource 1 mem: [0x90000000-0x9fffffff]
> pci_bus 0001:41: resource 0 mem: [0x0-0xfff]
> pci_bus 0001:41: resource 1 mem: [0x94000000-0x940fffff]
> pci_bus 0001:41: resource 2 pref mem [0x90000000-0x93ffffff]
> pci_bus 0001:42: resource 1 mem: [0xa0100000-0xa4ffffff]
> pci_bus 0001:42: resource 2 pref mem [0x90000000-0x93ffffff]
> pci_bus 0001:43: resource 1 mem: [0xa0100000-0xa2ffffff]
> pci_bus 0001:43: resource 2 pref mem [0x90000000-0x91ffffff]
> pci_bus 0001:44: resource 1 mem: [0xa3000000-0xa4ffffff]
> pci_bus 0001:44: resource 2 pref mem [0x92000000-0x93ffffff]
> bio: create slab <bio-0> at 0
> SCSI subsystem initialized
> usbcore: registered new interface driver usbfs
> usbcore: registered new interface driver hub
> usbcore: registered new device driver usb
> Switched to high resolution mode on CPU 0
> NET: Registered protocol family 2
> IP route cache hash table entries: 2048 (order: 1, 8192 bytes)
> TCP established hash table entries: 8192 (order: 4, 65536 bytes)
> TCP bind hash table entries: 8192 (order: 3, 32768 bytes)
> TCP: Hash tables configured (established 8192 bind 8192)
> TCP reno registered
> NET: Registered protocol family 1
> Trying to unpack rootfs image as initramfs...
> Freeing initrd memory: 3078k freed
> irq: irq 26 on host /interrupt-controller mapped to virtual irq 26
> irq: irq 1 on host /interrupt-controller mapped to virtual irq 20
> irq: irq 30 on host /interrupt-controller2 mapped to virtual irq 21
> irq: irq 26 on host /interrupt-controller1 mapped to virtual irq 22
> irq: irq 12 on host /interrupt-controller mapped to virtual irq 23
> I-pipe: Domain Xenomai registered.
> Xenomai: hal/powerpc started.
> Xenomai: real-time nucleus v2.4.10 (Flavor Crystal 7) loaded.
> Xenomai: starting native API services.
> Xenomai: starting POSIX services.
> Xenomai: starting RTDM services.
> Installing knfsd (copyright (C) 1996 okir@monad.swb.de).
> fuse init (API version 7.11)
> msgmni has been set to 498
> alg: No test for stdrng (krng)
> io scheduler noop registered
> io scheduler anticipatory registered (default)
> io scheduler deadline registered
> io scheduler cfq registered
> aer 0001:41:00.0:pcie12: service driver aer loaded
> aer 0001:42:01.0:pcie22: service driver aer loaded
> aer 0001:42:02.0:pcie22: service driver aer loaded
> pci_hotplug: PCI Hot Plug PCI Core version: 0.5
> Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
> serial8250.0: ttyS0 at MMIO 0xef600200 (irq = 26) is a 16550A
> serial8250.0: ttyS1 at MMIO 0xef600300 (irq = 20) is a 16550A
> console [ttyS1] enabled
> ef600200.serial: ttyS0 at MMIO 0xef600200 (irq = 26) is a 16550A
> ef600300.serial: ttyS1 at MMIO 0xef600300 (irq = 20) is a 16550A
> brd: module loaded
> Driver 'sd' needs updating - please use bus_type methods
> PPC 4xx OCP EMAC driver, version 3.54
> irq: irq 10 on host /interrupt-controller mapped to virtual irq 24
> irq: irq 11 on host /interrupt-controller mapped to virtual irq 25
> irq: irq 0 on host /interrupt-controller1 mapped to virtual irq 27
> irq: irq 1 on host /interrupt-controller1 mapped to virtual irq 29
> irq: irq 2 on host /interrupt-controller1 mapped to virtual irq 31
> MAL v2 /plb/mcmal, 2 TX channels, 2 RX channels
> RGMII /plb/opb/emac-rgmii@ef600b00 initialized with MDIO support
> irq: irq 24 on host /interrupt-controller mapped to virtual irq 32
> irq: irq 29 on host /interrupt-controller1 mapped to virtual irq 33
> /plb/opb/emac-rgmii@ef600b00: input 0 in RGMII mode
> eth0: EMAC-0 /plb/opb/ethernet@ef600900, MAC 00:90:f9:10:1a:08
> eth0: found Marvell 88E1111 Ethernet PHY (0x04)
> irq: irq 25 on host /interrupt-controller mapped to virtual irq 34
> irq: irq 31 on host /interrupt-controller1 mapped to virtual irq 35
> /plb/opb/emac-rgmii@ef600b00: input 1 in RGMII mode
> eth1: EMAC-1 /plb/opb/ethernet@ef600a00, MAC 00:90:f9:10:1a:09
> eth1: found Marvell 88E1111 Ethernet PHY (0x05)
> fc000000.nor_flash: Found 1 x16 devices at 0x0 in 16-bit bank
>  Intel/Sharp Extended Query Table at 0x010A
>  Intel/Sharp Extended Query Table at 0x010A
>  Intel/Sharp Extended Query Table at 0x010A
>  Intel/Sharp Extended Query Table at 0x010A
>  Intel/Sharp Extended Query Table at 0x010A
> Using buffer write method
> Using auto-unlock on power-up/resume
> cfi_cmdset_0001: Erase suspend on write enabled
> erase region 0: offset=0x0,size=0x8000,blocks=4
> erase region 1: offset=0x20000,size=0x20000,blocks=511
> RedBoot partition parsing not available
> Creating 7 MTD partitions on "fc000000.nor_flash":
> 0x000000000000-0x000000800000 : "kernel0"
> 0x000000800000-0x000001000000 : "kernel1"
> 0x000001000000-0x000001800000 : "kernel2"
> 0x000001800000-0x000003f40000 : "install"
> 0x000003f40000-0x000003f60000 : "env0"
> 0x000003f60000-0x000003f80000 : "env1"
> 0x000003f80000-0x000004000000 : "u-boot"
> irq: irq 8 on host /interrupt-controller mapped to virtual irq 36
> spi_ppc4xx_of ef600600.spi: driver initialized
> Initializing USB Mass Storage driver...
> usbcore: registered new interface driver usb-storage
> USB Mass Storage support registered.
> dwc_otg: version 2.60a 22-NOV-2006
> dwc_otg: Shared Tx FIFO mode
> dwc_otg: Using DMA mode
> dwc_otg dwc_otg.0: DWC OTG Controller
> dwc_otg dwc_otg.0: new USB bus registered, assigned bus number 1
> dwc_otg dwc_otg.0: irq 21, io mem 0x00000000
> dwc_otg: Init: Port Power? op_state=1
> dwc_otg: Init: Power Port (0)
> usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
> usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
> usb usb1: Product: DWC OTG Controller
> usb usb1: Manufacturer: Linux 2.6.30.3-00063-g0af2edc-dirty dwc_otg_hcd
> usb usb1: SerialNumber: dwc_otg.0
> usb usb1: configuration #1 chosen from 1 choice
> hub 1-0:1.0: USB hub found
> hub 1-0:1.0: 1 port detected
> i2c /dev entries driver
> irq: irq 2 on host /interrupt-controller mapped to virtual irq 37
> ibm-iic ef600400.i2c: using standard (100 kHz) mode
> irq: irq 7 on host /interrupt-controller mapped to virtual irq 38
> ibm-iic ef600500.i2c: using standard (100 kHz) mode
> lm75: probe of 0-0048 failed with error -121
> hwmon-vid: Unknown VRM version of your CPU
> PowerPC Book-E Watchdog Timer Loaded
> TCP cubic registered
> Initializing XFRM netlink socket
> NET: Registered protocol family 17
> NET: Registered protocol family 15
> RPC: Registered udp transport module.
> RPC: Registered tcp transport module.
> 802.1Q VLAN Support v1.8 Ben Greear <greearb@candelatech.com>
> All bugs added by David S. Miller <davem@redhat.com>
> usb 1-1: new high speed USB device using dwc_otg and address 2
> usb 1-1: New USB device found, idVendor=0634, idProduct=0655
> usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
> usb 1-1: Product: Real SSD eUSB 2GB
> usb 1-1: Manufacturer: Micron Technology
> usb 1-1: SerialNumber: 4BF0022700035321
> usb 1-1: configuration #1 chosen from 1 choice
> scsi0 : SCSI emulation for USB Mass Storage devices
> usb-storage: device found at 2
> usb-storage: waiting for device to settle before scanning
> eth0: link is down
> eth0: link is up, 100 HDX
> IP-Config: Complete:
>      device=eth0, addr=137.237.178.150, mask=255.255.255.0, gw=137.237.178.1,
>      host=flx-am, domain=, nis-domain=(none),
>      bootserver=137.237.178.9, rootserver=137.237.178.9, rootpath=
> Freeing unused kernel memory: 164k init
> at24 0-0050: 512 byte 24c04 EEPROM (writable)
> at24 0-0052: 512 byte 24c04 EEPROM (writable)
> scsi 0:0:0:0: Direct-Access     MICRON   eUSB DISK        1110 PQ: 0 ANSI: 0 CCS
> sd 0:0:0:0: Attached scsi generic sg0 type 0
> usb-storage: device scan complete
> sd 0:0:0:0: [sda] 3964928 512-byte hardware sectors: (2.03 GB/1.89 GiB)
> sd 0:0:0:0: [sda] Write Protect is off
> sd 0:0:0:0: [sda] Mode Sense: 43 00 00 00
> sd 0:0:0:0: [sda] Assuming drive cache: write through
> sd 0:0:0:0: [sda] Assuming drive cache: write through
>  sda: sda1 sda2 sda3 sda4
> sd 0:0:0:0: [sda] Attached SCSI disk
> kjournald starting.  Commit interval 5 seconds
> EXT3 FS on sda2, internal journal
> EXT3-fs: mounted filesystem with journal data mode.
> kjournald starting.  Commit interval 5 seconds
> EXT3 FS on sda1, internal journal
> EXT3-fs: mounted filesystem with journal data mode.
> kjournald starting.  Commit interval 5 seconds
> EXT3 FS on sda3, internal journal
> EXT3-fs: mounted filesystem with journal data mode.
> kjournald starting.  Commit interval 5 seconds
> EXT3 FS on sda4, internal journal
> EXT3-fs: mounted filesystem with journal data mode.
> at24 0-0050: 512 byte 24c04 EEPROM (writable)
> at24 0-0052: 512 byte 24c04 EEPROM (writable)
> dx83xx 0001:43:00.0: device not available because of BAR 0 [0xa1000000-0xa1ffffff] collisions
> dx83xx: probe of 0001:43:00.0 failed with error -22
> dx83xx 0001:44:00.0: device not available because of BAR 0 [0xa3000000-0xa3ffffff] collisions
> dx83xx: probe of 0001:44:00.0 failed with error -22

^ 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