LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] rionet: add memory access to simulated Ethernet over rapidio
From: Li Yang @ 2009-04-28 10:15 UTC (permalink / raw)
  To: akpm, galak, davem, mporter
  Cc: linuxppc-dev, Zhang Wei, Li Yang, linux-kernel, netdev
In-Reply-To: <1240913737-23773-3-git-send-email-leoli@freescale.com>

Through the newly added IO memory access of Rapidio, sender can
write directly to recipient's rx buffer, either by cpu or DMA engine.

Signed-off-by: Zhang Wei <zw@zh-kernel.org>
Signed-off-by: Li Yang <leoli@freescale.com>
---
 drivers/net/Kconfig  |   10 ++
 drivers/net/rionet.c |  365 +++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 371 insertions(+), 4 deletions(-)

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 214a92d..1e88e26 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2736,6 +2736,16 @@ config RIONET_RX_SIZE
 	depends on RIONET
 	default "128"
 
+config RIONET_MEMMAP
+	bool "Use memory map instead of message"
+	depends on RIONET
+	default n
+
+config RIONET_DMA
+	bool "Use DMA for memory mapping data transfer"
+	depends on RIONET_MEMMAP && FSL_DMA
+	default y
+
 config FDDI
 	tristate "FDDI driver support"
 	depends on (PCI || EISA || TC)
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
index ec59e29..c38e51e 100644
--- a/drivers/net/rionet.c
+++ b/drivers/net/rionet.c
@@ -1,6 +1,8 @@
 /*
  * rionet - Ethernet driver over RapidIO messaging services
  *
+ * Copyright (C) 2007-2009 Freescale Semiconductor, Inc.
+ *
  * Copyright 2005 MontaVista Software, Inc.
  * Matt Porter <mporter@kernel.crashing.org>
  *
@@ -23,6 +25,7 @@
 #include <linux/skbuff.h>
 #include <linux/crc32.h>
 #include <linux/ethtool.h>
+#include <linux/dmaengine.h>
 
 #define DRV_NAME        "rionet"
 #define DRV_VERSION     "0.2"
@@ -40,13 +43,48 @@ MODULE_LICENSE("GPL");
 			 NETIF_MSG_TX_ERR)
 
 #define RIONET_DOORBELL_JOIN	0x1000
+#ifdef CONFIG_RIONET_MEMMAP
+#define RIONET_DOORBELL_SEND	0x1001
+#define RIONET_DOORBELL_LEAVE	0x1002
+#else
 #define RIONET_DOORBELL_LEAVE	0x1001
+#endif
 
 #define RIONET_MAILBOX		0
 
 #define RIONET_TX_RING_SIZE	CONFIG_RIONET_TX_SIZE
 #define RIONET_RX_RING_SIZE	CONFIG_RIONET_RX_SIZE
 
+#define ERR(fmt, arg...) \
+	printk(KERN_ERR "ERROR %s - %s: " fmt,  __FILE__, __func__, ## arg)
+
+#ifdef CONFIG_RIONET_MEMMAP
+/* Definitions for rionet memory map driver */
+#define RIONET_DRVID		0x101
+#define RIONET_MAX_SK_DATA_SIZE	0x1000
+#define RIONET_MEM_RIO_BASE	0x10000000
+#define RIONET_TX_RX_BUFF_SIZE	(0x1000 * (128 + 128))
+#define RIONET_QUEUE_NEXT(x)	(((x) < 127) ? ((x) + 1) : 0)
+#define RIONET_QUEUE_INC(x)	(x = RIONET_QUEUE_NEXT(x))
+
+struct sk_data {
+	u8	data[0x1000];
+};
+
+#define RIONET_SKDATA_EN	0x80000000
+struct rionet_tx_rx_buff {
+	int		enqueue;		/* enqueue point */
+	int		dequeue;		/* dequeue point */
+	u32		size[128];		/* size[i] is skdata[i] size
+						 * the most high bit [31] is
+						 * enable bit. The
+						 * max size is 4096.
+						 */
+	u8		rev1[3576];
+	struct sk_data	skdata[128];		/* all size are 0x1000 * 128 */
+};
+#endif /* CONFIG_RIONET_MEMMAP */
+
 static LIST_HEAD(rionet_peers);
 
 struct rionet_private {
@@ -60,6 +98,19 @@ struct rionet_private {
 	spinlock_t lock;
 	spinlock_t tx_lock;
 	u32 msg_enable;
+#ifdef CONFIG_RIONET_MEMMAP
+	struct rionet_tx_rx_buff *rxbuff;
+	struct rionet_tx_rx_buff __iomem *txbuff;
+	dma_addr_t rx_addr;
+	phys_addr_t tx_addr;
+	struct resource *riores;
+#ifdef CONFIG_RIONET_DMA
+	struct dma_chan *txdmachan;
+	struct dma_chan *rxdmachan;
+	struct dma_client rio_dma_client;
+	spinlock_t rio_dma_event_lock;
+#endif
+#endif
 };
 
 struct rionet_peer {
@@ -90,6 +141,7 @@ static struct rio_dev **rionet_active;
 #define RIONET_MAC_MATCH(x)	(*(u32 *)x == 0x00010001)
 #define RIONET_GET_DESTID(x)	(*(u16 *)(x + 4))
 
+#ifndef CONFIG_RIONET_MEMMAP
 static int rionet_rx_clean(struct net_device *ndev)
 {
 	int i;
@@ -108,9 +160,11 @@ static int rionet_rx_clean(struct net_device *ndev)
 
 		rnet->rx_skb[i]->data = data;
 		skb_put(rnet->rx_skb[i], RIO_MAX_MSG_SIZE);
+		rnet->rx_skb[i]->dev = ndev;
 		rnet->rx_skb[i]->protocol =
 		    eth_type_trans(rnet->rx_skb[i], ndev);
 		error = netif_rx(rnet->rx_skb[i]);
+		rnet->rx_skb[i] = NULL;
 
 		if (error == NET_RX_DROP) {
 			ndev->stats.rx_dropped++;
@@ -128,6 +182,7 @@ static int rionet_rx_clean(struct net_device *ndev)
 
 	return i;
 }
+#endif
 
 static void rionet_rx_fill(struct net_device *ndev, int end)
 {
@@ -141,19 +196,86 @@ static void rionet_rx_fill(struct net_device *ndev, int end)
 		if (!rnet->rx_skb[i])
 			break;
 
+#ifndef CONFIG_RIONET_MEMMAP
 		rio_add_inb_buffer(rnet->mport, RIONET_MAILBOX,
 				   rnet->rx_skb[i]->data);
+#endif
 	} while ((i = (i + 1) % RIONET_RX_RING_SIZE) != end);
 
 	rnet->rx_slot = i;
 }
 
+#ifdef CONFIG_RIONET_MEMMAP
+static int rio_send_mem(struct sk_buff *skb,
+				struct net_device *ndev, struct rio_dev *rdev)
+{
+	struct rionet_private *rnet = netdev_priv(ndev);
+	int enqueue, dequeue;
+
+	if (!rdev)
+		return -EFAULT;
+
+	if (skb->len > RIONET_MAX_SK_DATA_SIZE) {
+		printk(KERN_ERR "Frame len is more than RIONET max sk_data!\n");
+		return -EINVAL;
+	}
+
+	rio_map_outb_region(rnet->mport, rdev->destid, rnet->riores,
+			rnet->tx_addr, 0);
+
+	enqueue = in_be32(&rnet->txbuff->enqueue);
+	dequeue = in_be32(&rnet->txbuff->dequeue);
+
+	if (!(in_be32(&rnet->txbuff->size[enqueue]) & RIONET_SKDATA_EN)
+			&& (RIONET_QUEUE_NEXT(enqueue) != dequeue)) {
+#ifdef CONFIG_RIONET_DMA
+		struct dma_device *dmadev;
+		struct dma_async_tx_descriptor *tx;
+		dma_cookie_t tx_cookie = 0;
+
+		dmadev = rnet->txdmachan->device;
+		tx = dmadev->device_prep_dma_memcpy(rnet->txdmachan,
+			(void *)rnet->txbuff->skdata[enqueue].data
+			  - (void *)rnet->txbuff rnet->tx_addr,
+			dma_map_single(&ndev->dev, skb->data, skb->len,
+			  DMA_TO_DEVICE), skb->len, DMA_CTRL_ACK);
+		if (!tx)
+			return -EFAULT;
+		tx_cookie = tx->tx_submit(tx);
+
+		dma_async_memcpy_issue_pending(rnet->txdmachan);
+		while (dma_async_memcpy_complete(rnet->txdmachan,
+				tx_cookie, NULL, NULL) == DMA_IN_PROGRESS) ;
+#else
+		memcpy(rnet->txbuff->skdata[enqueue].data, skb->data, skb->len);
+#endif /* CONFIG_RIONET_DMA */
+		out_be32(&rnet->txbuff->size[enqueue],
+						RIONET_SKDATA_EN | skb->len);
+		out_be32(&rnet->txbuff->enqueue,
+						RIONET_QUEUE_NEXT(enqueue));
+		in_be32(&rnet->txbuff->enqueue);	/* verify read */
+	} else if (netif_msg_tx_err(rnet))
+		printk(KERN_ERR "rionmet(memmap): txbuff is busy!\n");
+
+	rio_unmap_outb_region(rnet->mport, rnet->tx_addr);
+	rio_send_doorbell(rdev, RIONET_DOORBELL_SEND);
+	return 0;
+}
+#endif
+
 static int rionet_queue_tx_msg(struct sk_buff *skb, struct net_device *ndev,
 			       struct rio_dev *rdev)
 {
 	struct rionet_private *rnet = netdev_priv(ndev);
 
+#ifdef CONFIG_RIONET_MEMMAP
+	int ret = 0;
+	ret = rio_send_mem(skb, ndev, rdev);
+	if (ret)
+		return ret;
+#else
 	rio_add_outb_message(rnet->mport, rdev, 0, skb->data, skb->len);
+#endif
 	rnet->tx_skb[rnet->tx_slot] = skb;
 
 	ndev->stats.tx_packets++;
@@ -165,6 +287,19 @@ static int rionet_queue_tx_msg(struct sk_buff *skb, struct net_device *ndev,
 	++rnet->tx_slot;
 	rnet->tx_slot &= (RIONET_TX_RING_SIZE - 1);
 
+#ifdef CONFIG_RIONET_MEMMAP
+	while (rnet->tx_cnt && (rnet->ack_slot != rnet->tx_slot)) {
+		/* dma unmap single */
+		dev_kfree_skb_any(rnet->tx_skb[rnet->ack_slot]);
+		rnet->tx_skb[rnet->ack_slot] = NULL;
+		++rnet->ack_slot;
+		rnet->ack_slot &= (RIONET_TX_RING_SIZE - 1);
+		rnet->tx_cnt--;
+	}
+
+	if (rnet->tx_cnt < RIONET_TX_RING_SIZE)
+		netif_wake_queue(ndev);
+#endif
 	if (netif_msg_tx_queued(rnet))
 		printk(KERN_INFO "%s: queued skb %8.8x len %8.8x\n", DRV_NAME,
 		       (u32) skb, skb->len);
@@ -211,6 +346,92 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 	return 0;
 }
 
+#ifdef CONFIG_RIONET_MEMMAP
+static void rio_recv_mem(struct net_device *ndev)
+{
+	struct rionet_private *rnet = netdev_priv(ndev);
+	struct sk_buff *skb;
+	u32 enqueue, dequeue, size;
+	int error = 0;
+#ifdef CONFIG_RIONET_DMA
+	dma_cookie_t rx_cookie = 0;
+	struct dma_device *dmadev;
+	struct dma_async_tx_descriptor *tx;
+#endif
+
+	dequeue = rnet->rxbuff->dequeue;
+	enqueue = rnet->rxbuff->enqueue;
+
+	while (enqueue != dequeue) {
+		size = rnet->rxbuff->size[dequeue];
+		if (!(size & RIONET_SKDATA_EN))
+			return;
+		size &= ~RIONET_SKDATA_EN;
+
+		skb = dev_alloc_skb(size + 2);
+		if (!skb)
+			return;
+
+#ifdef CONFIG_RIONET_DMA
+		dmadev = rnet->rxdmachan->device;
+		tx = dmadev->device_prep_dma_memcpy(rnet->rxdmachan,
+			dma_map_single(&ndev->dev, skb_put(skb, size),
+			  size, DMA_FROM_DEVICE),
+			(void *)rnet->rxbuff->skdata[dequeue].data
+			  - (void *)rnet->rxbuff + rnet->rx_addr,
+			size, DMA_CTRL_ACK);
+		if (!tx)
+			return;
+		rx_cookie = tx->tx_submit(tx);
+		dma_async_memcpy_issue_pending(rnet->rxdmachan);
+		while (dma_async_memcpy_complete(rnet->rxdmachan,
+				rx_cookie, NULL, NULL) == DMA_IN_PROGRESS);
+#else
+		memcpy(skb_put(skb, size),
+				rnet->rxbuff->skdata[dequeue].data,
+				size);
+#endif /* CONFIG_RIONET_DMA */
+		skb->dev = ndev;
+		skb->protocol = eth_type_trans(skb, ndev);
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+		error = netif_rx(skb);
+
+		rnet->rxbuff->size[dequeue] &= ~RIONET_SKDATA_EN;
+		rnet->rxbuff->dequeue = RIONET_QUEUE_NEXT(dequeue);
+		dequeue = RIONET_QUEUE_NEXT(dequeue);
+
+		if (error == NET_RX_DROP) {
+			ndev->stats.rx_dropped++;
+		} else if (error == NET_RX_BAD) {
+			if (netif_msg_rx_err(rnet))
+				printk(KERN_WARNING "%s: bad rx packet\n",
+				       DRV_NAME);
+			ndev->stats.rx_errors++;
+		} else {
+			ndev->stats.rx_packets++;
+			ndev->stats.rx_bytes += RIO_MAX_MSG_SIZE;
+		}
+	}
+}
+
+static void rionet_inb_recv_event(struct rio_mport *mport, void *dev_id)
+{
+	struct net_device *ndev = dev_id;
+	struct rionet_private *rnet = netdev_priv(ndev);
+	unsigned long flags;
+
+	if (netif_msg_intr(rnet))
+		printk(KERN_INFO "%s: inbound memory data receive event\n",
+		       DRV_NAME);
+
+	spin_lock_irqsave(&rnet->lock, flags);
+	rio_recv_mem(ndev);
+	spin_unlock_irqrestore(&rnet->lock, flags);
+}
+#endif
+
+
 static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u16 tid,
 			       u16 info)
 {
@@ -232,6 +453,10 @@ static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u
 		}
 	} else if (info == RIONET_DOORBELL_LEAVE) {
 		rionet_active[sid] = NULL;
+#ifdef CONFIG_RIONET_MEMMAP
+	} else if (info == RIONET_DOORBELL_SEND) {
+		rionet_inb_recv_event(mport, ndev);
+#endif
 	} else {
 		if (netif_msg_intr(rnet))
 			printk(KERN_WARNING "%s: unhandled doorbell\n",
@@ -239,6 +464,7 @@ static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u
 	}
 }
 
+#ifndef CONFIG_RIONET_MEMMAP
 static void rionet_inb_msg_event(struct rio_mport *mport, void *dev_id, int mbox, int slot)
 {
 	int n;
@@ -281,6 +507,58 @@ static void rionet_outb_msg_event(struct rio_mport *mport, void *dev_id, int mbo
 
 	spin_unlock(&rnet->lock);
 }
+#endif
+
+#ifdef CONFIG_RIONET_DMA
+static enum dma_state_client rionet_dma_event(struct dma_client *client,
+		struct dma_chan *chan, enum dma_state state)
+{
+	struct rionet_private *rnet = container_of(client,
+			struct rionet_private, rio_dma_client);
+	enum dma_state_client ack = DMA_DUP;
+
+	spin_lock(&rnet->lock);
+	switch (state) {
+	case DMA_RESOURCE_AVAILABLE:
+		if (!rnet->txdmachan) {
+			ack = DMA_ACK;
+			rnet->txdmachan = chan;
+		} else if (!rnet->rxdmachan) {
+			ack = DMA_ACK;
+			rnet->rxdmachan = chan;
+		}
+		break;
+	case DMA_RESOURCE_REMOVED:
+		if (rnet->txdmachan == chan) {
+			ack = DMA_ACK;
+			rnet->txdmachan = NULL;
+		} else if (rnet->rxdmachan == chan) {
+			ack = DMA_ACK;
+			rnet->rxdmachan = NULL;
+		}
+		break;
+	default:
+		break;
+	}
+	spin_unlock(&rnet->lock);
+	return ack;
+}
+
+static int rionet_dma_register(struct rionet_private *rnet)
+{
+	int rc = 0;
+	spin_lock_init(&rnet->rio_dma_event_lock);
+	rnet->rio_dma_client.event_callback = rionet_dma_event;
+	dma_cap_set(DMA_MEMCPY, rnet->rio_dma_client.cap_mask);
+	dma_async_client_register(&rnet->rio_dma_client);
+	dma_async_client_chan_request(&rnet->rio_dma_client);
+
+	if (!rnet->txdmachan || !rnet->rxdmachan)
+		rc = -ENODEV;
+
+	return rc;
+}
+#endif
 
 static int rionet_open(struct net_device *ndev)
 {
@@ -297,21 +575,63 @@ static int rionet_open(struct net_device *ndev)
 					RIONET_DOORBELL_JOIN,
 					RIONET_DOORBELL_LEAVE,
 					rionet_dbell_event)) < 0)
-		goto out;
+		return rc;
+
+#ifdef CONFIG_RIONET_MEMMAP
+	if (!request_rio_region(RIONET_MEM_RIO_BASE, RIONET_TX_RX_BUFF_SIZE,
+				ndev->name, 0)) {
+		dev_err(&ndev->dev, "RapidIO space busy\n");
+		rc = -EBUSY;
+		goto out1;
+	}
 
+	rnet->riores = kmalloc(sizeof(struct resource), GFP_KERNEL);
+	if (!rnet->riores) {
+		rc = -ENOMEM;
+		goto out2;
+	}
+	rnet->riores->start = RIONET_MEM_RIO_BASE;
+	rnet->riores->end = RIONET_MEM_RIO_BASE + RIONET_TX_RX_BUFF_SIZE - 1;
+	rnet->rxbuff = dma_alloc_coherent(&ndev->dev, RIONET_TX_RX_BUFF_SIZE,
+			&rnet->rx_addr, GFP_KERNEL);
+	if (!rnet->rxbuff) {
+		rc = -ENOMEM;
+		goto out3;
+	}
+	rc = rio_map_inb_region(rnet->mport, rnet->riores, rnet->rx_addr, 0);
+	if (rc) {
+		rc = -EBUSY;
+		goto out4;
+	}
+	
+	/* Use space right after the doorbell window, aligned to
+	 * size of RIONET_TX_RX_BUFF_SIZE */
+	rnet->tx_addr = rnet->mport->iores.start + 0x500000;
+	rnet->txbuff = ioremap(rnet->tx_addr, resource_size(rnet->riores));
+	if (!rnet->txbuff) {
+		rc = -ENOMEM;
+		goto out5;
+	}
+#ifdef CONFIG_RIONET_DMA
+	rc = rionet_dma_register(rnet);
+	if (rc)
+		goto out6;
+#endif /* CONFIG_RIONET_DMA */
+#else
 	if ((rc = rio_request_inb_mbox(rnet->mport,
 				       (void *)ndev,
 				       RIONET_MAILBOX,
 				       RIONET_RX_RING_SIZE,
 				       rionet_inb_msg_event)) < 0)
-		goto out;
+		goto out1;
 
 	if ((rc = rio_request_outb_mbox(rnet->mport,
 					(void *)ndev,
 					RIONET_MAILBOX,
 					RIONET_TX_RING_SIZE,
 					rionet_outb_msg_event)) < 0)
-		goto out;
+		goto out8;
+#endif
 
 	/* Initialize inbound message ring */
 	for (i = 0; i < RIONET_RX_RING_SIZE; i++)
@@ -344,8 +664,31 @@ static int rionet_open(struct net_device *ndev)
 		if (pwdcsr & RIO_DOORBELL_AVAIL)
 			rio_send_doorbell(peer->rdev, RIONET_DOORBELL_JOIN);
 	}
+	return 0;
 
-      out:
+#ifndef CONFIG_RIONET_MEMMAP
+out8:
+	rio_release_inb_mbox(rnet->mport, RIONET_MAILBOX);
+#else
+#ifdef CONFIG_RIONET_DMA
+out6:
+	iounmap(rnet->txbuff);
+#endif
+out5:
+	rio_unmap_inb_region(rnet->mport, rnet->rx_addr);
+out4:
+	dma_free_coherent(&ndev->dev, RIONET_TX_RX_BUFF_SIZE,
+			rnet->rxbuff, rnet->rx_addr);
+	rnet->rxbuff = NULL;
+	rnet->txbuff = NULL;
+out3:
+	kfree(rnet->riores);
+out2:
+	release_rio_region(RIONET_MEM_RIO_BASE, RIONET_TX_RX_BUFF_SIZE);
+#endif
+out1:
+	rio_release_inb_dbell(rnet->mport, RIONET_DOORBELL_JOIN,
+			RIONET_DOORBELL_LEAVE);
 	return rc;
 }
 
@@ -374,8 +717,22 @@ static int rionet_close(struct net_device *ndev)
 
 	rio_release_inb_dbell(rnet->mport, RIONET_DOORBELL_JOIN,
 			      RIONET_DOORBELL_LEAVE);
+#ifdef CONFIG_RIONET_MEMMAP
+	rio_unmap_inb_region(rnet->mport, rnet->rx_addr);
+	iounmap(rnet->txbuff);
+	dma_free_coherent(&ndev->dev, RIONET_TX_RX_BUFF_SIZE,
+			rnet->rxbuff, rnet->rx_addr);
+	kfree(rnet->riores);
+	release_rio_region(RIONET_MEM_RIO_BASE, RIONET_TX_RX_BUFF_SIZE);
+	rnet->rxbuff = NULL;
+	rnet->txbuff = NULL;
+#ifdef CONFIG_RIONET_DMA
+	dma_async_client_unregister(&rnet->rio_dma_client);
+#endif
+#else
 	rio_release_inb_mbox(rnet->mport, RIONET_MAILBOX);
 	rio_release_outb_mbox(rnet->mport, RIONET_MAILBOX);
+#endif
 
 	return 0;
 }
-- 
1.5.4

^ permalink raw reply related

* [PATCH] powerpc: add memory map support to Freescale RapioIO block
From: Li Yang @ 2009-04-28 10:15 UTC (permalink / raw)
  To: akpm, galak, davem, mporter
  Cc: linuxppc-dev, Zhang Wei, Li Yang, linux-kernel, netdev
In-Reply-To: <1240913737-23773-2-git-send-email-leoli@freescale.com>

The RIO memory map functions are used to support direct IO memory access
to RapidIO space.  The patch adds its support for Freescale RapidIO block
driver.

Signed-off-by: Zhang Wei <zw@zh-kernel.org>
Signed-off-by: Li Yang <leoli@freescale.com>
---
 arch/powerpc/sysdev/fsl_rio.c |  217 ++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 215 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index fa0720f..7056dc0 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -31,6 +31,9 @@
 #define IRQ_RIO_TX(m)		(((struct rio_priv *)(m->priv))->txirq)
 #define IRQ_RIO_RX(m)		(((struct rio_priv *)(m->priv))->rxirq)
 
+#define IS_64BIT_DMA		((sizeof(dma_addr_t) == 8) ? 1 : 0)
+#define IS_64BIT_PHYS		((sizeof(phys_addr_t) == 8) ? 1 : 0)
+
 #define RIO_ATMU_REGS_OFFSET	0x10c00
 #define RIO_P_MSG_REGS_OFFSET	0x11000
 #define RIO_S_MSG_REGS_OFFSET	0x13000
@@ -40,6 +43,15 @@
 #define RIO_ISR_AACR_AA		0x1	/* Accept All ID */
 #define RIO_MAINT_WIN_SIZE	0x400000
 #define RIO_DBELL_WIN_SIZE	0x1000
+#define RIO_MAX_INB_ATMU	4
+#define RIO_MAX_OUTB_ATMU	8
+#define RIO_INB_ATMU_REGS_OFFSET	0x10de0
+#define RIO_ATMU_EN_MASK	0x80000000
+
+#define RIO_NREAD		0x4
+#define RIO_NWRITE		0x4
+#define RIO_NWRITE_R		0x5
+#define RIO_NREAD_R		0x5
 
 #define RIO_MSG_OMR_MUI		0x00000002
 #define RIO_MSG_OSR_TE		0x00000080
@@ -83,6 +95,15 @@ struct rio_atmu_regs {
 	u32 pad3[3];
 };
 
+struct rio_inb_atmu_regs {
+	u32 riwtar;
+	u32 pad1;
+	u32 riwbar;
+	u32 pad2;
+	u32 riwar;
+	u32 pad3[3];
+};
+
 struct rio_msg_regs {
 	u32 omr;
 	u32 osr;
@@ -341,6 +362,188 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid,
 }
 
 /**
+ * fsl_rio_map_inb_mem -- Mapping inbound memory region.
+ * @mport: RapidIO master port
+ * @lstart: Local memory space start address.
+ * @rstart: RapidIO space start address.
+ * @size: The mapping region size.
+ * @flags: Flags for mapping. 0 for using default flags.
+ *
+ * Return: 0 -- Success.
+ *
+ * This function will create the inbound mapping
+ * from rstart to lstart.
+ */
+static int fsl_rio_map_inb_mem(struct rio_mport *mport, dma_addr_t lstart,
+		resource_size_t rstart,	resource_size_t size, u32 flags)
+{
+	int i;
+	struct rio_priv *priv = mport->priv;
+	struct rio_inb_atmu_regs __iomem *inbatmu = (struct rio_inb_atmu_regs *)
+				(priv->regs_win + RIO_INB_ATMU_REGS_OFFSET) - 1;
+	int size_ffs;
+	resource_size_t align;
+
+	if (flags == 0)
+		flags = (RIO_NREAD_R << 4) | RIO_NWRITE_R;
+
+	align = (size < 0x1000) ? 0x1000 : 1 << (__ilog2(size - 1) + 1);
+
+	/* Align the size */
+	if ((lstart + size) > (_ALIGN_DOWN(lstart, align) + align)) {
+		size_ffs = __ffs(_ALIGN_DOWN(lstart + size - 1, align));
+		size = 1 << (size_ffs +	(((_ALIGN_DOWN(lstart, 1 << size_ffs) +
+				(1 << size_ffs)) < (lstart + size)) ? 1 : 0));
+	} else
+		size = align;
+
+	if ((lstart & (size - 1)) != (rstart & (size - 1))) {
+		dev_err(mport->dev, "The local address 0x%llx can not be "
+			"aligned to the same size 0x%llx with the RapidIO "
+			"space address 0x%llx!\n", (unsigned long long)lstart,
+			(unsigned long long)size, (unsigned long long)rstart);
+		return -EINVAL;
+	}
+
+	/* Search for free inbound ATMU */
+	for (i = 1;
+		(i <= RIO_MAX_INB_ATMU) && (inbatmu->riwar & RIO_ATMU_EN_MASK);
+		i++, inbatmu--)
+		;
+
+	if (i > RIO_MAX_INB_ATMU) {
+		dev_err(mport->dev, "No free inbound ATMU!\n");
+		return -EBUSY;
+	}
+	out_be32(&inbatmu->riwtar, ((IS_64BIT_DMA ? (lstart >> 32)
+				& 0xf : 0) << 20) | ((lstart >> 12) & 0xfffff));
+	out_be32(&inbatmu->riwbar, ((IS_64BIT_DMA ? (rstart >> 32)
+				& 0x3 : 0) << 20) | ((rstart >> 12) & 0xfffff));
+	out_be32(&inbatmu->riwar, 0x80000000 | (0xf << 20)
+				| ((flags & 0xff) << 12)
+				| (__ilog2(size) - 1));
+	return 0;
+}
+
+/**
+ * fsl_rio_map_outb_mem -- Mapping outbound memory region.
+ * @mport: RapidIO master port
+ * @lstart: Local memory space start address.
+ * @rstart: RapidIO space start address.
+ * @size: The mapping region size.
+ * @tid: The target RapidIO device id.
+ * @flags: Flags for mapping. 0 for using default flags.
+ *
+ * Return: 0 -- Success.
+ *
+ * This function will create the outbound mapping
+ * from lstart to rstart.
+ */
+static int fsl_rio_map_outb_mem(struct rio_mport *mport, phys_addr_t lstart,
+		resource_size_t rstart,	resource_size_t size,
+		u16 tid, u32 flags)
+{
+	int i;
+	struct rio_priv *priv = mport->priv;
+	struct rio_atmu_regs __iomem *outbatmu = (struct rio_atmu_regs *)
+			(priv->regs_win + RIO_ATMU_REGS_OFFSET) + 1;
+	int size_ffs;
+	resource_size_t align;
+
+	if (flags == 0)
+		flags = (RIO_NREAD << 4) | RIO_NWRITE_R;
+
+	align = (size < 0x1000) ? 0x1000 : 1 << (__ilog2(size - 1) + 1);
+
+	/* Align the size */
+	if ((lstart + size) > (_ALIGN_DOWN(lstart, align) + align)) {
+		size_ffs = __ffs(_ALIGN_DOWN(lstart + size - 1, align));
+		size = 1 << (size_ffs +	(((_ALIGN_DOWN(lstart, 1 << size_ffs) +
+				(1 << size_ffs)) < (lstart + size)) ? 1 : 0));
+	} else
+		size = align;
+
+	if ((lstart & (size - 1)) != (rstart & (size - 1))) {
+		dev_err(mport->dev, "The local address 0x%llx can not be "
+			"aligned to the same size 0x%llx with the RapidIO "
+			"space address 0x%llx!\n", (unsigned long long)lstart,
+			(unsigned long long)size, (unsigned long long)rstart);
+		return -EINVAL;
+	}
+
+	/* Search for free outbound ATMU */
+	for (i = 1;
+	      (i <= RIO_MAX_OUTB_ATMU) && (outbatmu->rowar & RIO_ATMU_EN_MASK);
+	      i++, outbatmu++)
+		;
+
+	if (i > RIO_MAX_OUTB_ATMU) {
+		dev_err(mport->dev, "No free outbound ATMU!\n");
+		return -EBUSY;
+	}
+	out_be32(&outbatmu->rowtar, ((tid & 0x3ff) << 22)
+			| ((IS_64BIT_PHYS ? (rstart >> 32) & 0x3 : 0) << 20)
+			| ((rstart >> 12) & 0xfffff));
+	if (mport->phy_type == RIO_PHY_SERIAL)
+		out_be32(&outbatmu->rowtear, tid >> 10);
+	out_be32(&outbatmu->rowbar, ((IS_64BIT_PHYS ?
+					(lstart >> 32) & 0xf : 0) << 20)
+					| ((lstart >> 12) & 0xfffff));
+	out_be32(&outbatmu->rowar, 0x80000000
+				| ((flags & 0xff) << 12)
+				| (__ilog2(size) - 1));
+	return 0;
+}
+
+/**
+ * fsl_rio_unmap_inb_mem -- Unmapping inbound memory region.
+ * @mport: RapidIO master port
+ * @lstart: Local memory space start address.
+ */
+static void fsl_rio_unmap_inb_mem(struct rio_mport *mport,
+				dma_addr_t lstart)
+{
+	int i;
+	struct rio_priv *priv = mport->priv;
+	struct rio_inb_atmu_regs __iomem *inbatmu = (struct rio_inb_atmu_regs *)
+			(priv->regs_win + RIO_INB_ATMU_REGS_OFFSET) - 1;
+
+	/* Search for inbound ATMU */
+	for (i = 1; i <= RIO_MAX_INB_ATMU ; i++, inbatmu--) {
+		u32 tar = ((IS_64BIT_DMA ? (lstart >> 32) & 0xf : 0) << 20)
+			| ((lstart >> 12) & 0xfffff);
+		if (inbatmu->riwtar == tar) {
+			out_be32(&inbatmu->riwar, ~(RIO_ATMU_EN_MASK));
+			return;
+		}
+	}
+}
+
+/**
+ * fsl_rio_unmap_outb_mem -- Unmapping outbound memory region.
+ * @mport: RapidIO master port
+ * @lstart: Local memory space start address.
+ */
+static void fsl_rio_unmap_outb_mem(struct rio_mport *mport,
+				phys_addr_t lstart)
+{
+	int i;
+	struct rio_priv *priv = mport->priv;
+	struct rio_atmu_regs __iomem *outbatmu = (struct rio_atmu_regs *)
+			(priv->regs_win + RIO_ATMU_REGS_OFFSET) + 1;
+
+	/* Search for outbound ATMU */
+	for (i = 1; i <= RIO_MAX_OUTB_ATMU ; i++, outbatmu++) {
+		u32 bar = ((IS_64BIT_PHYS ? (lstart >> 32) & 0xf : 0) << 20)
+			| ((lstart >> 12) & 0xfffff);
+		if (outbatmu->rowbar == bar) {
+			out_be32(&outbatmu->rowar, ~(RIO_ATMU_EN_MASK));
+			return;
+		}
+	}
+}
+
+/**
  * rio_hw_add_outb_message - Add message to the MPC85xx outbound message queue
  * @mport: Master port with outbound message queue
  * @rdev: Target of outbound message
@@ -951,6 +1154,13 @@ static int fsl_rio_get_cmdline(char *s)
 
 __setup("riohdid=", fsl_rio_get_cmdline);
 
+static struct rio_mem_ops fsl_mem_ops = {
+	.map_inb = fsl_rio_map_inb_mem,
+	.map_outb = fsl_rio_map_outb_mem,
+	.unmap_inb = fsl_rio_unmap_inb_mem,
+	.unmap_outb = fsl_rio_unmap_outb_mem,
+};
+
 static inline void fsl_rio_info(struct device *dev, u32 ccsr)
 {
 	const char *str;
@@ -1026,8 +1236,9 @@ int fsl_rio_setup(struct of_device *dev)
 		return -EFAULT;
 	}
 	dev_info(&dev->dev, "Of-device full name %s\n", dev->node->full_name);
-	dev_info(&dev->dev, "Regs start 0x%08x size 0x%08x\n",	regs.start,
-						regs.end - regs.start + 1);
+	dev_info(&dev->dev, "Regs start 0x%llx size 0x%llx\n",
+			(unsigned long long)regs.start,
+			(unsigned long long)(regs.end - regs.start + 1));
 
 	dt_range = of_get_property(dev->node, "ranges", &rlen);
 	if (!dt_range) {
@@ -1067,6 +1278,7 @@ int fsl_rio_setup(struct of_device *dev)
 	port = kzalloc(sizeof(struct rio_mport), GFP_KERNEL);
 	port->id = 0;
 	port->index = 0;
+	port->dev = &dev->dev;
 
 	priv = kzalloc(sizeof(struct rio_priv), GFP_KERNEL);
 	if (!priv) {
@@ -1095,6 +1307,7 @@ int fsl_rio_setup(struct of_device *dev)
 	priv->dev = &dev->dev;
 
 	port->ops = ops;
+	port->mops = &fsl_mem_ops;
 	port->host_deviceid = fsl_rio_get_hdid(port->id);
 
 	port->priv = priv;
-- 
1.5.4

^ permalink raw reply related

* [PATCH] powerpc/fsl_rio: use LAW address from device tree
From: Li Yang @ 2009-04-28 10:15 UTC (permalink / raw)
  To: akpm, galak, davem, mporter; +Cc: linuxppc-dev, Li Yang, linux-kernel, netdev
In-Reply-To: <1240913737-23773-1-git-send-email-leoli@freescale.com>

Instead of fixed address in old code.

Signed-off-by: Li Yang <leoli@freescale.com>
---
 arch/powerpc/sysdev/fsl_rio.c |   12 +++++++-----
 1 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index abdb124..fa0720f 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -1077,8 +1077,9 @@ int fsl_rio_setup(struct of_device *dev)
 
 	INIT_LIST_HEAD(&port->dbells);
 	port->iores.start = law_start;
-	port->iores.end = law_start + law_size;
+	port->iores.end = law_start + law_size - 1;
 	port->iores.flags = IORESOURCE_MEM;
+	port->iores.name = "rio_io_win";
 
 	priv->bellirq = irq_of_parse_and_map(dev->node, 2);
 	priv->txirq = irq_of_parse_and_map(dev->node, 3);
@@ -1156,14 +1157,15 @@ int fsl_rio_setup(struct of_device *dev)
 		out_be32((priv->regs_win + RIO_ISR_AACR), RIO_ISR_AACR_AA);
 
 	/* Configure maintenance transaction window */
-	out_be32(&priv->maint_atmu_regs->rowbar, 0x000c0000);
-	out_be32(&priv->maint_atmu_regs->rowar, 0x80077015);
+	out_be32(&priv->maint_atmu_regs->rowbar, law_start >> 12);
+	out_be32(&priv->maint_atmu_regs->rowar, 0x80077015);	/* 4M */
 
 	priv->maint_win = ioremap(law_start, RIO_MAINT_WIN_SIZE);
 
 	/* Configure outbound doorbell window */
-	out_be32(&priv->dbell_atmu_regs->rowbar, 0x000c0400);
-	out_be32(&priv->dbell_atmu_regs->rowar, 0x8004200b);
+	out_be32(&priv->dbell_atmu_regs->rowbar,
+			(law_start + RIO_MAINT_WIN_SIZE) >> 12);
+	out_be32(&priv->dbell_atmu_regs->rowar, 0x8004200b);	/* 4k */
 	fsl_rio_doorbell_init(port);
 
 	return 0;
-- 
1.5.4

^ permalink raw reply related

* [PATCH] rapidio: add common mapping APIs for RapidIO memory access
From: Li Yang @ 2009-04-28 10:15 UTC (permalink / raw)
  To: akpm, galak, davem, mporter
  Cc: linuxppc-dev, Zhang Wei, Li Yang, linux-kernel, netdev
In-Reply-To: <2a27d3730904280316l7049bddbie914907b16ccfff6@mail.gmail.com>

Add the mapping functions used to support direct IO memory access of
rapidIO.

Signed-off-by: Zhang Wei <zw@zh-kernel.org>
Signed-off-by: Li Yang <leoli@freescale.com>
---
 drivers/rapidio/rio.c   |   95 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/rio.h     |   25 ++++++++++++
 include/linux/rio_drv.h |   24 +++++++++---
 3 files changed, 138 insertions(+), 6 deletions(-)

diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c
index 6395c78..224a076 100644
--- a/drivers/rapidio/rio.c
+++ b/drivers/rapidio/rio.c
@@ -2,6 +2,8 @@
  * RapidIO interconnect services
  * (RapidIO Interconnect Specification, http://www.rapidio.org)
  *
+ * Copyright (C) 2007-2009 Freescale Semiconductor, Inc.
+ *
  * Copyright 2005 MontaVista Software, Inc.
  * Matt Porter <mporter@kernel.crashing.org>
  *
@@ -24,11 +26,23 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/hardirq.h>
 
 #include "rio.h"
 
 static LIST_HEAD(rio_mports);
 
+static DEFINE_SPINLOCK(rio_config_lock);
+
+struct resource rio_resource = {
+	.name	= "RapidIO GSM",
+	.start	= 0,
+	.end	= -1,
+	.flags	= IORESOURCE_MEM,
+};
+EXPORT_SYMBOL(rio_resource);
+
 /**
  * rio_local_get_device_id - Get the base/extended device id for a port
  * @port: RIO master port from which to get the deviceid
@@ -333,6 +347,87 @@ int rio_release_outb_dbell(struct rio_dev *rdev, struct resource *res)
 }
 
 /**
+ * rio_map_inb_region -- Mapping inbound memory region.
+ * @mport: Master port.
+ * @mem: Memory struction for mapping.
+ * @rflags: Flags for mapping.
+ *
+ * Return: 0 -- Success.
+ *
+ * This function will create the mapping from rio space to local mem.
+ */
+int rio_map_inb_region(struct rio_mport *mport, struct resource *rio_res,
+			dma_addr_t local, u32 rflags)
+{
+	int rc = 0;
+	unsigned long flags;
+
+	if (!mport->mops)
+		return -1;
+	spin_lock_irqsave(&rio_config_lock, flags);
+	rc = mport->mops->map_inb(mport, local, rio_res->start,
+				resource_size(rio_res), rflags);
+	spin_unlock_irqrestore(&rio_config_lock, flags);
+	return rc;
+}
+
+/**
+ * rio_map_outb_region -- Mapping outbound memory region.
+ * @mport: Master port.
+ * @tid: Target RapidIO device id.
+ * @mem: Memory struction for mapping.
+ * @rflags: Flags for mapping.
+ *
+ * Return: 0 -- Success.
+ *
+ * This function will create the mapping from local iomem to rio space.
+ */
+int rio_map_outb_region(struct rio_mport *mport, u16 tid,
+		struct resource *rio_res, phys_addr_t lstart, u32 rflags)
+{
+	int rc = 0;
+	unsigned long flags;
+
+	if (!mport->mops)
+		return -1;
+	spin_lock_irqsave(&rio_config_lock, flags);
+	rc = mport->mops->map_outb(mport, lstart, rio_res->start,
+				resource_size(rio_res), tid, rflags);
+	spin_unlock_irqrestore(&rio_config_lock, flags);
+	return rc;
+}
+
+/**
+ * rio_unmap_inb_region -- Unmap the inbound memory region
+ * @mport: Master port
+ * @mem: Memory struction for unmapping.
+ */
+void rio_unmap_inb_region(struct rio_mport *mport, dma_addr_t lstart)
+{
+	unsigned long flags;
+	if (!mport->mops)
+		return;
+	spin_lock_irqsave(&rio_config_lock, flags);
+	mport->mops->unmap_inb(mport, lstart);
+	spin_unlock_irqrestore(&rio_config_lock, flags);
+}
+
+/**
+ * rio_unmap_outb_region -- Unmap the outbound memory region
+ * @mport: Master port
+ * @mem: Memory struction for unmapping.
+ */
+void rio_unmap_outb_region(struct rio_mport *mport, phys_addr_t lstart)
+{
+	unsigned long flags;
+	if (!mport->mops)
+		return;
+	spin_lock_irqsave(&rio_config_lock, flags);
+	mport->mops->unmap_outb(mport, lstart);
+	spin_unlock_irqrestore(&rio_config_lock, flags);
+}
+
+/**
  * rio_mport_get_feature - query for devices' extended features
  * @port: Master port to issue transaction
  * @local: Indicate a local master port or remote device access
diff --git a/include/linux/rio.h b/include/linux/rio.h
index dc0c755..dd61538 100644
--- a/include/linux/rio.h
+++ b/include/linux/rio.h
@@ -176,6 +176,7 @@ struct rio_mport {
 	struct rio_msg outb_msg[RIO_MAX_MBOX];
 	int host_deviceid;	/* Host device ID */
 	struct rio_ops *ops;	/* maintenance transaction functions */
+	struct rio_mem_ops *mops; /* Memory functions */
 	unsigned char id;	/* port ID, unique among all ports */
 	unsigned char index;	/* port index, unique among all port
 				   interfaces of the same type */
@@ -185,6 +186,7 @@ struct rio_mport {
 				 */
 	enum rio_phy_type phy_type;	/* RapidIO phy type */
 	unsigned char name[40];
+	struct device *dev;
 	void *priv;		/* Master port private data */
 };
 
@@ -319,6 +321,29 @@ struct rio_route_ops {
 			 u16 table, u16 route_destid, u8 * route_port);
 };
 
+extern struct resource rio_resource;
+#define request_rio_region(start, n, name, flag) \
+		__request_region(&rio_resource, (start), (n), (name), (flag))
+#define release_rio_region(start, n) __release_region(&rio_resource, (start), (n))
+
+/**
+ * Struct for RIO memory definition.
+ * @map_inb: The function for mapping inbound memory window.
+ * @map_outb: The function for mapping outbound memory window.
+ * @unmap_inb: The function for unmapping inbound memory window.
+ * @unmap_outb: The function for unmapping outbound memory window.
+ */
+struct rio_mem_ops {
+	int (*map_inb) (struct rio_mport *, dma_addr_t lstart,
+			resource_size_t rstart,
+			resource_size_t size, u32 flags);
+	int (*map_outb) (struct rio_mport *, phys_addr_t lstart,
+			resource_size_t rstart,
+			resource_size_t size, u16 tid, u32 flags);
+	void (*unmap_inb) (struct rio_mport *, dma_addr_t lstart);
+	void (*unmap_outb) (struct rio_mport *, phys_addr_t lstart);
+};
+
 /* Architecture and hardware-specific functions */
 extern int rio_init_mports(void);
 extern void rio_register_mport(struct rio_mport *);
diff --git a/include/linux/rio_drv.h b/include/linux/rio_drv.h
index c93a58a..685f2da 100644
--- a/include/linux/rio_drv.h
+++ b/include/linux/rio_drv.h
@@ -332,6 +332,16 @@ static inline void rio_init_dbell_res(struct resource *res, u16 start, u16 end)
 	res->flags = RIO_RESOURCE_DOORBELL;
 }
 
+static inline void rio_init_io_res(struct resource *res, resource_size_t start,
+		resource_size_t size, const char *name, unsigned long flag)
+{
+	memset(res, 0, sizeof(struct resource));
+	res->start = start;
+	res->end = start + size - 1;
+	res->name = name;
+	res->flags = flag;
+}
+
 /**
  * RIO_DEVICE - macro used to describe a specific RIO device
  * @dev: the 16 bit RIO device ID
@@ -406,12 +416,13 @@ extern int rio_release_inb_dbell(struct rio_mport *, u16, u16);
 extern struct resource *rio_request_outb_dbell(struct rio_dev *, u16, u16);
 extern int rio_release_outb_dbell(struct rio_dev *, struct resource *);
 
-/* Memory region management */
-int rio_claim_resource(struct rio_dev *, int);
-int rio_request_regions(struct rio_dev *, char *);
-void rio_release_regions(struct rio_dev *);
-int rio_request_region(struct rio_dev *, int, char *);
-void rio_release_region(struct rio_dev *, int);
+/* Memory low-level mapping functions */
+extern int rio_map_inb_region(struct rio_mport *, struct resource *,
+				dma_addr_t, u32);
+extern int rio_map_outb_region(struct rio_mport *, u16, struct resource *,
+				phys_addr_t, u32);
+extern void rio_unmap_inb_region(struct rio_mport *, dma_addr_t);
+extern void rio_unmap_outb_region(struct rio_mport *, phys_addr_t);
 
 /* LDM support */
 int rio_register_driver(struct rio_driver *);
@@ -461,5 +472,6 @@ extern u16 rio_local_get_device_id(struct rio_mport *port);
 extern struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from);
 extern struct rio_dev *rio_get_asm(u16 vid, u16 did, u16 asm_vid, u16 asm_did,
 				   struct rio_dev *from);
+extern u32 rio_get_mport_id(struct rio_mport *);
 
 #endif				/* LINUX_RIO_DRV_H */
-- 
1.5.4

^ permalink raw reply related

* [PATCH 0/5] rapidio: adding memory mapping IO support and misc fixes
From: Li Yang @ 2009-04-28 10:16 UTC (permalink / raw)
  To: akpm, Kumar Gala, David Miller, mporter
  Cc: linuxppc-dev Development, linux-kernel, Netdev

The patch series add MMIO support to Linux rapidio and fix a few nits.
 The patches cross rapidio, netdev, powerpc sub-systems.  It will be
good for them to go through one tree.  Probably Andrew?  As the
previous rapidio patches are mostly merged by you.

- Leo

^ permalink raw reply

* Re: [PATCH 2/2] powerpc/86xx: Add new LAW & MCM device tree nodes for all 86xx systems
From: Martyn Welch @ 2009-04-28  9:19 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev, devicetree-discuss
In-Reply-To: <1240855188-24879-2-git-send-email-galak@kernel.crashing.org>

Kumar Gala wrote:
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
>  arch/powerpc/boot/dts/gef_ppc9a.dts        |   13 +++++++++++++
>  arch/powerpc/boot/dts/gef_sbc310.dts       |   13 +++++++++++++
>  arch/powerpc/boot/dts/gef_sbc610.dts       |   13 +++++++++++++
>  arch/powerpc/boot/dts/mpc8610_hpcd.dts     |   13 +++++++++++++
>  arch/powerpc/boot/dts/mpc8641_hpcn.dts     |   13 +++++++++++++
>  arch/powerpc/boot/dts/mpc8641_hpcn_36b.dts |   13 +++++++++++++
>  arch/powerpc/boot/dts/sbc8641d.dts         |   13 +++++++++++++
>  7 files changed, 91 insertions(+), 0 deletions(-)
>   
Am I right in thinking that this patch doesn't (as yet) enable any added 
functionality, or have I missed something?

I assume this is destined for next (as it relies on Becky's 
"powerpc/86xx: Add 36-bit device tree for mpc8641hpcn"), assuming this, 
fwiw, seems good to me.

Martyn

-- 
Martyn Welch MEng MPhil MIET (Principal Software Engineer)   T:+44(0)1327322748
GE Fanuc Intelligent Platforms Ltd,        |Registered in England and Wales
Tove Valley Business Park, Towcester,      |(3828642) at 100 Barbirolli Square,
Northants, NN12 6PF, UK T:+44(0)1327359444 |Manchester,M2 3AB  VAT:GB 927559189

^ permalink raw reply

* Re: [PATCH] net: Fix ucc_geth.c handling of phy 'interface' property.
From: David Miller @ 2009-04-28  9:12 UTC (permalink / raw)
  To: grant.likely; +Cc: Joakim.Tjernlund, linuxppc-dev, afleming, netdev, scottwood
In-Reply-To: <fa686aa40904271050kb3159cbw52c0c1dba3076f3e@mail.gmail.com>

From: Grant Likely <grant.likely@secretlab.ca>
Date: Mon, 27 Apr 2009 11:50:20 -0600

> On Mon, Apr 27, 2009 at 11:36 AM, Scott Wood <scottwood@freescale.com=
> wrote:
>> On Mon, Apr 27, 2009 at 09:36:13AM -0600, Grant Likely wrote:
>>> From: Grant Likely <grant.likely@secretlab.ca>
>>>
>>> Previous rework to ucc_geth.c to add of_mdio support (net: Rework
>>> ucc_geth driver to use of_mdio infrastructure) added a block of
>>> code which broke older openfirmware device trees which use an
>>> 'interface' property in the phy node to describe the connection
>>> between the MAC and the PHY. =A0This patch removes the offending bl=
urb.
>> [snip]
>>> =A0 =A0 =A0 prop =3D of_get_property(np, "phy-connection-type", NUL=
L);
>>> =A0 =A0 =A0 if (!prop) {
>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* handle interface property present in=
 old trees */
>>> - =A0 =A0 =A0 =A0 =A0 =A0 if (!phy)
>>> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENODEV;
>>> -
>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 prop =3D of_get_property(phy, "interfac=
e", NULL);
>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (prop !=3D NULL) {
>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 phy_interface =3D enet_=
to_phy_interface[*prop];
>>
>> The above test only makes a difference when there is no phy node -- =
so I
>> don't see how it was breaking device trees that had a phy node (with=
 or
>> without an "interface" property). =A0I can see it breaking fixed lin=
k
>> device trees, though.
> =

> Sorry, you're right.  I got myself confused when I was writing the
> description.  This patch fixes breakage when using a fixed-link and
> there is no phy-connection-type property.

Patch applied with commit message fixed up.

^ permalink raw reply

* Re: [PATCH v2] fs_enet: Remove dead code
From: David Miller @ 2009-04-28  9:06 UTC (permalink / raw)
  To: galak; +Cc: netdev, linuxppc-dev
In-Reply-To: <1240436148-5456-1-git-send-email-galak@kernel.crashing.org>

From: Kumar Gala <galak@kernel.crashing.org>
Date: Wed, 22 Apr 2009 16:35:48 -0500

> CONFIG_DUET doesn't exist anymore, remove all the code that exists to
> support it.
> 
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>

I took the liberty of simplifying fs_init() even further
when applying this.  It had become:

	int r = foo();
	if (r != 0)
		return r;
	return 0;

which is just plain:

	return foo();

fs_enet: Remove dead code

CONFIG_DUET doesn't exist anymore, remove all the code that exists to
support it.

[ Simplify fs_init() even further -DaveM ]

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
 drivers/net/fs_enet/fs_enet-main.c |   39 +-----------------------------------
 drivers/net/fs_enet/fs_enet.h      |    5 ----
 drivers/net/fs_enet/mac-fec.c      |   34 -------------------------------
 3 files changed, 1 insertions(+), 77 deletions(-)

diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index 9604aae..b892c3a 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -941,30 +941,6 @@ extern void fs_mii_disconnect(struct net_device *dev);
 
 /**************************************************************************************/
 
-/* handy pointer to the immap */
-void __iomem *fs_enet_immap = NULL;
-
-static int setup_immap(void)
-{
-#ifdef CONFIG_CPM1
-	fs_enet_immap = ioremap(IMAP_ADDR, 0x4000);
-	WARN_ON(!fs_enet_immap);
-#elif defined(CONFIG_CPM2)
-	fs_enet_immap = cpm2_immr;
-#endif
-
-	return 0;
-}
-
-static void cleanup_immap(void)
-{
-#if defined(CONFIG_CPM1)
-	iounmap(fs_enet_immap);
-#endif
-}
-
-/**************************************************************************************/
-
 #ifdef CONFIG_FS_ENET_HAS_FEC
 #define IS_FEC(match) ((match)->data == &fs_fec_ops)
 #else
@@ -1144,25 +1120,12 @@ static struct of_platform_driver fs_enet_driver = {
 
 static int __init fs_init(void)
 {
-	int r = setup_immap();
-	if (r != 0)
-		return r;
-
-	r = of_register_platform_driver(&fs_enet_driver);
-	if (r != 0)
-		goto out;
-
-	return 0;
-
-out:
-	cleanup_immap();
-	return r;
+	return of_register_platform_driver(&fs_enet_driver);
 }
 
 static void __exit fs_cleanup(void)
 {
 	of_unregister_platform_driver(&fs_enet_driver);
-	cleanup_immap();
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h
index 85a4bab..ef01e09 100644
--- a/drivers/net/fs_enet/fs_enet.h
+++ b/drivers/net/fs_enet/fs_enet.h
@@ -194,9 +194,4 @@ extern const struct fs_ops fs_scc_ops;
 
 /*******************************************************************/
 
-/* handy pointer to the immap */
-extern void __iomem *fs_enet_immap;
-
-/*******************************************************************/
-
 #endif
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index 14e5753..ca7bcb8 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -245,10 +245,6 @@ static void set_multicast_list(struct net_device *dev)
 
 static void restart(struct net_device *dev)
 {
-#ifdef CONFIG_DUET
-	immap_t *immap = fs_enet_immap;
-	u32 cptr;
-#endif
 	struct fs_enet_private *fep = netdev_priv(dev);
 	fec_t __iomem *fecp = fep->fec.fecp;
 	const struct fs_platform_info *fpi = fep->fpi;
@@ -315,36 +311,6 @@ static void restart(struct net_device *dev)
 	FW(fecp, ievent, 0xffc0);
 	FW(fecp, ivec, (virq_to_hw(fep->interrupt) / 2) << 29);
 
-	/*
-	 * adjust to speed (only for DUET & RMII)
-	 */
-#ifdef CONFIG_DUET
-	if (fpi->use_rmii) {
-		cptr = in_be32(&immap->im_cpm.cp_cptr);
-		switch (fs_get_fec_index(fpi->fs_no)) {
-		case 0:
-			cptr |= 0x100;
-			if (fep->speed == 10)
-				cptr |= 0x0000010;
-			else if (fep->speed == 100)
-				cptr &= ~0x0000010;
-			break;
-		case 1:
-			cptr |= 0x80;
-			if (fep->speed == 10)
-				cptr |= 0x0000008;
-			else if (fep->speed == 100)
-				cptr &= ~0x0000008;
-			break;
-		default:
-			BUG();	/* should never happen */
-			break;
-		}
-		out_be32(&immap->im_cpm.cp_cptr, cptr);
-	}
-#endif
-
-
 	FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);	/* MII enable */
 	/*
 	 * adjust to duplex mode
-- 
1.6.2.4

^ permalink raw reply related

* Re: "leds: Add openfirmware platform device support" breaks sparc
From: David Miller @ 2009-04-28  9:01 UTC (permalink / raw)
  To: grant.likely
  Cc: monstr, linuxppc-dev, rpurdie, smaclennan, sparclinux, akpm,
	tpiepho, john.williams
In-Reply-To: <fa686aa40904272059q604d61c5u1fe584a2166545f1@mail.gmail.com>

From: Grant Likely <grant.likely@secretlab.ca>
Date: Mon, 27 Apr 2009 21:59:39 -0600

>     of: make of_(un)register_platform_driver common code.
> 
>     Some drivers using of_register_platform_driver() wrapper break on sparc
>     because the wrapper isn't in the header file.  This patch moves it from
>     Microblaze and PowerPC implementations and makes it common code.
> 
>     Signed-off-by: Grant Likely <grant.likely@secretlab.ca>

Looks great:

Acked-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply

* Re: Please revert edada399 and 9203fc9c
From: Sam Ravnborg @ 2009-04-28  8:35 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, Linus Torvalds, linux-kernel, Tim Abbott
In-Reply-To: <18934.35969.872225.70725@cargo.ozlabs.ibm.com>

On Tue, Apr 28, 2009 at 02:56:33PM +1000, Paul Mackerras wrote:
> Linus,
> 
> Please revert commits edada399 ("powerpc: Use TEXT_TEXT macro in
> linker script.") and 9203fc9c ("powerpc: Use __REF macro instead of
> old .text.init.refok."), which depends on edada399.
> 
> Commit edada399 breaks the build because it moves the __ftr_alt_*
> sections of a file away from the .text section, causing link failures
> due to relative conditional branch targets being too far away from the
> branch instructions.  This happens on pretty much all 64-bit powerpc
> configs.
> 
> Clearly these patches were never even build-tested.  They were never
> acked by the powerpc maintainer (Ben) - because he was on vacation -
> and they weren't sent to the deputy maintainer (me) or the relevant
> mailing list (linuxppc-dev).

This is partly my fault :-(
I acked them as I did not see the issue with conditional branches.
Could I ask you to add a comment to the lds file about this.

	Sam

^ permalink raw reply

* Re: drivers/video/logo/logo_linux_mono.c build error
From: Geert Uytterhoeven @ 2009-04-28  7:24 UTC (permalink / raw)
  To: Stephen Rothwell; +Cc: linuxppc-dev, Andrew Morton
In-Reply-To: <20090428135202.9c9bbadb.sfr@canb.auug.org.au>

On Tue, 28 Apr 2009, Stephen Rothwell wrote:
> On Mon, 27 Apr 2009 14:50:31 -0700 Andrew Morton <akpm@linux-foundation.org> wrote:
> > powerpc allmodconfig, current mainline:
> > 
> > drivers/video/logo/logo_linux_mono.c:11: error: logo_linux_mono_data causes a section type conflict
> > 
> > switching it from __initconst to __initdata "fixes" it.
> 
> Interesting.  The program that generates the .c file above produces
> __initdata for me ...

I assume Andrew once built in that tree using the recent logo patches that
  1. Makes the logos const and switch them from __initdata to __initconst,
  2. Fix the missing dependency of the generated files on the generator program.
Hence if you revert the logo patches, you have to manually remove the generated
files.

Is my assumption correct?

With kind regards,

Geert Uytterhoeven
Software Architect
Techsoft Centre

Technology and Software Centre Europe
The Corporate Village · Da Vincilaan 7-D1 · B-1935 Zaventem · Belgium

Phone:    +32 (0)2 700 8453
Fax:      +32 (0)2 700 8622
E-mail:   Geert.Uytterhoeven@sonycom.com
Internet: http://www.sony-europe.com/

A division of Sony Europe (Belgium) N.V.
VAT BE 0413.825.160 · RPR Brussels
Fortis · BIC GEBABEBB · IBAN BE41293037680010

^ permalink raw reply

* read data from FIFO memories to SDRAM with DMA on MPC8247
From: Sauce.Cheng @ 2009-04-28  7:21 UTC (permalink / raw)
  To: linuxppc-dev


hi all:
now there was one question like this following:
there are two chips which are dual-port FIFO memories on my target board.
I attempt two read data with the way of DMA from FIFO to SDRAM
In my point, i need a driver of DMA and a driver of FIFO
but i have no idea at all that what should i do about this.

anyone can give some suggestions to me?
i.e. what i can do at frist? or what i can do in addition to the thing what
i said.

thanks
Sauce
-- 
View this message in context: http://www.nabble.com/read-data-from-FIFO-memories-to-SDRAM-with-DMA-on-MPC8247-tp23271549p23271549.html
Sent from the linuxppc-dev mailing list archive at Nabble.com.

^ permalink raw reply

* RE: [PATCH 2/2] powerpc/85xx: Add new LAW & MCM device tree nodes for all85xx systems
From: Liu Dave-R63238 @ 2009-04-28  6:41 UTC (permalink / raw)
  To: Kumar Gala, linuxppc-dev; +Cc: devicetree-discuss
In-Reply-To: <1240864725-29003-2-git-send-email-galak@kernel.crashing.org>

> Subject: [PATCH 2/2] powerpc/85xx: Add new LAW & MCM device=20
> tree nodes for all85xx systems

One nit/typo, the tittle of the two patches should be "ECM"

^ permalink raw reply

* Re: [PATCH] 83xx: add support for the kmeter1 board.
From: Heiko Schocher @ 2009-04-28  4:42 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <20090427180503.GB10292@ld0162-tx32.am.freescale.net>

Hello Scott,

Scott Wood wrote:
> On Mon, Apr 27, 2009 at 07:38:38AM +0200, Heiko Schocher wrote:
>> 1) add in the soc node an "errata" node and in this "errata" node
>>    we can add all CPU specific errata as an example the qe_enet10
>>    errata, which above code covers:
> 
> What about errata discovered after the device tree is deployed?

Didn;t know that there are such errata. Ok, this is a problem.

>>         soc8360@e0000000 {
>> 	[...]
>>                 errata {
>>                         device_type = "errata";
> 
> device_type is deprecated except for a couple of legacy uses.  Please do
> not add new ones.

Ok.

>>                         compatible = "fsl,mpc83xx_errata";
> 
> To be bound to by an "errata driver"? :-P

Why not ;-) ?

>>                         #address-cells = <1>;
>>                         #size-cells = <1>;
>>
>>                         qe_enet10@14a8 {
>>                                 device_type = "errata";
>>                                 compatible = "fsl,mpc83xx_errata_qe_enet10";
>>                                 reg = <0x14a8 0x08>;
> 
> But that register is part of the "QE parallel I/O port" block (even if it
> happens to be undocumented within that block), not part of the "QE ENET10
> erratum" block.  The device tree describes the hardware, not what you
> want to do with it.

Hmm.. isn;t this an errata for a buggy hardware? Why not describing this
in the dts?

> The presence of the erratum itself is indicated by the presence of the
> buggy device, possibly in conjunction with SVR if the device tree is not
> specific enough.

Ah, Ok, that was just an idea ... so, where and how to solve the qe_enet10
errata without using get_immrbase() (and I vote not to solve it as it
actuall is in board specific code, maybe as i proposed in an earlier mail
in the ucc_geth.c driver?)?

bye
Heiko
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

^ permalink raw reply

* [git pull] Please pull powerpc.git merge branch
From: Paul Mackerras @ 2009-04-28  5:55 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linuxppc-dev, akpm, linux-kernel

Linus,

Please pull from the 'merge' branch of

git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc.git merge

to get a collection of bug fixes for powerpc.

Thanks,
Paul.

 MAINTAINERS                           |    2 +
 arch/powerpc/boot/4xx.c               |   56 +++++++++++++++++++++++++--------
 arch/powerpc/boot/dts/gef_ppc9a.dts   |    1 +
 arch/powerpc/include/asm/elf.h        |    1 +
 arch/powerpc/include/asm/mmu.h        |    6 ----
 arch/powerpc/include/asm/ppc-opcode.h |   11 +-----
 arch/powerpc/kernel/cputable.c        |    2 +
 arch/powerpc/mm/tlb_nohash_low.S      |   16 +--------
 arch/powerpc/platforms/cell/Kconfig   |    5 ++-
 arch/powerpc/platforms/ps3/setup.c    |    4 --
 10 files changed, 54 insertions(+), 50 deletions(-)

Geoff Levand (1):
      powerpc/ps3: Fix build error on UP

Josh Boyer (1):
      maintainers: Fix PowerPC 4xx git tree

Kumar Gala (2):
      Revert "powerpc: Add support for early tlbilx opcode"
      powerpc: ppc32 needs elf_read_implies_exec()

Martyn Welch (1):
      powerpc/86xx: Add device_type entry to soc for ppc9a

Michael Ellerman (1):
      powerpc/cell: Select PCI for IBM_CELL_BLADE AND CELLEB

Stephen Rothwell (1):
      powerpc: fix for long standing bug noticed by gcc 4.4.0

Valentine Barshak (1):
      powerpc/44x: Correct memory size calculation for denali-based boards

^ permalink raw reply

* [PATCH 1/2] powerpc: Enable MMU feature sections for inline asm
From: Michael Neuling @ 2009-04-28  5:03 UTC (permalink / raw)
  To: Michael Neuling, Paul Mackerras, Benjamin Herrenschmidt
  Cc: linuxppc-dev, Milton Miller
In-Reply-To: <1240895017.938097.293555352690.qpush@pale>

From: Milton Miller <miltonm@bga.com>

powerpc: Enable MMU feature sections for inline asm

This adds the ability to do MMU feature sections for inline asm.

Signed-off-by: Milton Miller <miltonm@bga.com>
Signed-off-by: Michael Neuling <mikey@neuling.org>
---

 arch/powerpc/include/asm/feature-fixups.h |   25 ++++++++++++++++++++-----
 1 file changed, 20 insertions(+), 5 deletions(-)

Index: linux-2.6-ozlabs/arch/powerpc/include/asm/feature-fixups.h
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/include/asm/feature-fixups.h
+++ linux-2.6-ozlabs/arch/powerpc/include/asm/feature-fixups.h
@@ -8,8 +8,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#ifdef __ASSEMBLY__
-
 /*
  * Feature section common macros
  *
@@ -23,10 +21,12 @@
 /* 64 bits kernel, 32 bits code (ie. vdso32) */
 #define FTR_ENTRY_LONG		.llong
 #define FTR_ENTRY_OFFSET	.long 0xffffffff; .long
+#elif defined(CONFIG_PPC64)
+#define FTR_ENTRY_LONG		.llong
+#define FTR_ENTRY_OFFSET	.llong
 #else
-/* 64 bit kernel 64 bit code, or 32 bit kernel 32 bit code */
-#define FTR_ENTRY_LONG		PPC_LONG
-#define FTR_ENTRY_OFFSET	PPC_LONG
+#define FTR_ENTRY_LONG		.long
+#define FTR_ENTRY_OFFSET	.long
 #endif
 
 #define START_FTR_SECTION(label)	label##1:
@@ -141,6 +141,21 @@ label##5:					       	\
 #define ALT_FW_FTR_SECTION_END_IFCLR(msk)	\
 	ALT_FW_FTR_SECTION_END_NESTED_IFCLR(msk, 97)
 
+#ifndef __ASSEMBLY__
+
+#define ASM_MMU_FTR_IF_X(string, estring, msk, val)		\
+	stringify_in_c(BEGIN_MMU_FTR_SECTION)			\
+	string "; "						\
+	stringify_in_c(MMU_FTR_SECTION_ELSE)			\
+	estring "; "						\
+	stringify_in_c(ALT_MMU_FTR_SECTION_END((msk), (val)))
+
+#define ASM_MMU_FTR_IFSET(string, estring, msk)			\
+	ASM_MMU_FTR_IF_X(string, estring, (msk), (msk))
+
+#define ASM_MMU_FTR_IFCLR(string, estring, msk)			\
+	ASM_MMU_FTR_IF_X(string, estring, (msk), 0)
+
 #endif /* __ASSEMBLY__ */
 
 /* LWSYNC feature sections */

^ permalink raw reply

* [PATCH 2/2] powerpc: Add 2.06 tlbie mnemonics
From: Michael Neuling @ 2009-04-28  5:03 UTC (permalink / raw)
  To: Michael Neuling, Paul Mackerras, Benjamin Herrenschmidt
  Cc: linuxppc-dev, Milton Miller
In-Reply-To: <1240895017.938097.293555352690.qpush@pale>

From: Milton Miller <miltonm@bga.com>

This adds the PowerPC 2.06 tlbie mnemonics and keeps backwards
compatibilty for CPUs before 2.06.

Only useful for bare metal systems.  

Signed-off-by: Milton Miller <miltonm@bga.com>
Signed-off-by: Michael Neuling <mikey@neuling.org>
---

 arch/powerpc/include/asm/ppc-opcode.h |    3 +++
 arch/powerpc/kernel/cputable.c        |    6 ++++--
 arch/powerpc/mm/hash_native_64.c      |   11 +++++++++--
 3 files changed, 16 insertions(+), 4 deletions(-)

Index: linux-2.6-ozlabs/arch/powerpc/include/asm/ppc-opcode.h
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/include/asm/ppc-opcode.h
+++ linux-2.6-ozlabs/arch/powerpc/include/asm/ppc-opcode.h
@@ -79,4 +79,7 @@
 #define PPC_WAIT(w)		stringify_in_c(.long PPC_INST_WAIT | \
 					__PPC_WC(w))
 
+#define TLBIE(lp,a) \
+	stringify_in_c(.long 0x7c000264 | ((a) << 11) | ((lp) << 21))
+
 #endif /* _ASM_POWERPC_PPC_OPCODE_H */
Index: linux-2.6-ozlabs/arch/powerpc/kernel/cputable.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/kernel/cputable.c
+++ linux-2.6-ozlabs/arch/powerpc/kernel/cputable.c
@@ -425,7 +425,8 @@ static struct cpu_spec __initdata cpu_sp
 		.cpu_name		= "POWER7 (architected)",
 		.cpu_features		= CPU_FTRS_POWER7,
 		.cpu_user_features	= COMMON_USER_POWER7,
-		.mmu_features		= MMU_FTR_HPTE_TABLE,
+		.mmu_features		= MMU_FTR_HPTE_TABLE |
+			MMU_FTR_TLBIE_206,
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.machine_check		= machine_check_generic,
@@ -438,7 +439,8 @@ static struct cpu_spec __initdata cpu_sp
 		.cpu_name		= "POWER7 (raw)",
 		.cpu_features		= CPU_FTRS_POWER7,
 		.cpu_user_features	= COMMON_USER_POWER7,
-		.mmu_features		= MMU_FTR_HPTE_TABLE,
+		.mmu_features		= MMU_FTR_HPTE_TABLE |
+			MMU_FTR_TLBIE_206,
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 6,
Index: linux-2.6-ozlabs/arch/powerpc/mm/hash_native_64.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/mm/hash_native_64.c
+++ linux-2.6-ozlabs/arch/powerpc/mm/hash_native_64.c
@@ -27,6 +27,7 @@
 #include <asm/cputable.h>
 #include <asm/udbg.h>
 #include <asm/kexec.h>
+#include <asm/ppc-opcode.h>
 
 #ifdef DEBUG_LOW
 #define DBG_LOW(fmt...) udbg_printf(fmt)
@@ -49,14 +50,19 @@ static inline void __tlbie(unsigned long
 	case MMU_PAGE_4K:
 		va &= ~0xffful;
 		va |= ssize << 8;
-		asm volatile("tlbie %0,0" : : "r" (va) : "memory");
+ 		asm volatile(ASM_MMU_FTR_IFCLR("tlbie %0,0", TLBIE(%1,%0), %2)
+			     : : "r" (va), "r"(0), "i" (MMU_FTR_TLBIE_206)
+			     : "memory");
 		break;
 	default:
 		penc = mmu_psize_defs[psize].penc;
 		va &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
 		va |= penc << 12;
 		va |= ssize << 8;
-		asm volatile("tlbie %0,1" : : "r" (va) : "memory");
+		va |= 1; /* L */
+ 		asm volatile(ASM_MMU_FTR_IFCLR("tlbie %0,1", TLBIE(%1,%0), %2)
+			     : : "r" (va), "r"(0), "i" (MMU_FTR_TLBIE_206)
+			     : "memory");
 		break;
 	}
 }
@@ -80,6 +86,7 @@ static inline void __tlbiel(unsigned lon
 		va &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
 		va |= penc << 12;
 		va |= ssize << 8;
+		va |= 1; /* L */
 		asm volatile(".long 0x7c000224 | (%0 << 11) | (1 << 21)"
 			     : : "r"(va) : "memory");
 		break;

^ permalink raw reply

* [PATCH 0/2] powerpc: tlbie implementation for PowerPC ISA 2.06
From: Michael Neuling @ 2009-04-28  5:03 UTC (permalink / raw)
  To: Michael Neuling, Paul Mackerras, Benjamin Herrenschmidt
  Cc: linuxppc-dev, Milton Miller
In-Reply-To: <3293F2F8-95B7-443C-8284-7F82D30F966B@kernel.crashing.org>

These patches implement the PowerPC ISA 2.06 tlbie mnemonics

Signed-off-by: Michael Neuling <mikey@neuling.org>
--- 
This version attempts to address issues raised by Kumar and Benh.
- Moves from CPU_FTR to MMU_FTR
- Moves #define of tlbie to ppc-opcode.h

^ permalink raw reply

* Re: removing get_immrbase()??
From: David Gibson @ 2009-04-28  4:26 UTC (permalink / raw)
  To: Grant Likely; +Cc: Scott Wood, Linuxppc-dev Development, Timur Tabi
In-Reply-To: <fa686aa40904230653j6855f8bai5248b250eb3ef515@mail.gmail.com>

On Thu, Apr 23, 2009 at 07:53:11AM -0600, Grant Likely wrote:
> On Wed, Apr 22, 2009 at 3:31 PM, Kumar Gala <galak@kernel.crashing.org> wrote:
> >
> > On Apr 22, 2009, at 3:16 PM, Timur Tabi wrote:
> >
> >> Scott Wood wrote:
> >>>
> >>> Timur Tabi wrote:
> >>>>>
> >>>>>      these two are related and seem like we could look for "fsl,cpm2"
> >>>>
> >>>> That's okay, as long as you don't break compatibility with older
> >>>> device trees that don't have that property, unless you can demonstrate
> >>>> that these trees would never work with the current kernel anyway.
> >>>
> >>> All CPM2 device trees should have fsl,cpm2 listed in the compatible of
> >>> the CPM node.
> >>
> >> Yes, but did they always have that compatible field?  I'm concerned
> >> about situations where someone updates his kernel but not his device
> >> tree.  This is a scenerio that we always need to try to support.
> >
> > I disagree.  If you update your kernel you should update your device tree
> > (thus we have .dts in the kernel tree and not somewhere else).
> 
> Not always possible.  The device tree may be 'softer' than firmware,
> and easier to update, but it is still firmer than the kernel.  That
> is

Again, this is not inherent, it's a platform design choice.  It's this
way for modern u-boot, but not for all platforms.

> why so much effort has been spent to not break compatibility with
> older device trees.

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

^ permalink raw reply

* Re: removing get_immrbase()??
From: David Gibson @ 2009-04-28  4:25 UTC (permalink / raw)
  To: Anton Vorontsov; +Cc: Scott Wood, Linuxppc-dev Development, Timur Tabi
In-Reply-To: <20090423135005.GA18462@oksana.dev.rtsoft.ru>

On Thu, Apr 23, 2009 at 05:50:05PM +0400, Anton Vorontsov wrote:
> On Thu, Apr 23, 2009 at 08:02:20AM -0500, Timur Tabi wrote:
> > David Gibson wrote:
> > 
> > > It's not so much point of view as situation.  Putting the device tree
> > > in the firmware and putting the device tree in the kernel are both
> > > valid choices, with their own distinct advantages and drawbacks. 
> > 
> > I was under the impression that the reason we put the device trees in
> > the kernel is because we didn't have a better place to put them.
> > Keeping them in the kernel repository was just convenient.
> > 
> > So I personally don't consider the *location* of the DTS files to be a
> > basis for deciding what they really mean.
> 
> I'm not sure why are we trying to make things harder for ourselves?
> x86 has a long history fighting with bogus bioses/dmi/acpi tables,
> up to the point where they completely ignore any information that
> BIOS provides, because that information is unreliable or hard to
> deal with.
> 
> With FDT (i.e. not hard-coded OF), we have a great opportunity to
> keep both device tree and Linux code legacyjunk-free.
> 
> All we have to do is to declare one simple thing: don't put
> device-tree into the read-only memory. Upgrading device tree blob
> in the rewritable NOR/NAND flashes is safe in overwhelming cases,
> just as safe as upgrading kernel image in the NOR/NAND.
> 
> And for those who didn't listen our pleases, i.e. for those
> who put device-tree blob into some kind of ROM or dangerous-
> to-upgrade memory or region of memory, we can always provide
> boot wrappers, and thus isolate the legacy stuff. I mean isolate
> it in their small legacy world, if anyone actually cares about
> these cases.

Indeed, this is a large part of the idea for the flattened device
tree.  Which is why I don't understand why when the idea of dtbs has
been floated, everyone seems to have been in a rush to put the blobs
into the firmware.  That's certainly one approach, and a good one for
certain needs (one kernel binary on many platforms, for example), but
putting the blob in the kernel is also an entirely valid approach and
avoids some drawbacks of having the blob in the firmware.

We're never going to get away from having shitty firmwares, but at
least with fdts we can isolate the handling of them from the bulk of
the kernel.

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

^ permalink raw reply

* Re: removing get_immrbase()??
From: David Gibson @ 2009-04-28  4:21 UTC (permalink / raw)
  To: Timur Tabi; +Cc: Scott Wood, Linuxppc-dev Development
In-Reply-To: <49F066DC.402@freescale.com>

On Thu, Apr 23, 2009 at 08:02:20AM -0500, Timur Tabi wrote:
> David Gibson wrote:
> 
> > It's not so much point of view as situation.  Putting the device tree
> > in the firmware and putting the device tree in the kernel are both
> > valid choices, with their own distinct advantages and drawbacks. 
> 
> I was under the impression that the reason we put the device trees in
> the kernel is because we didn't have a better place to put them.
> Keeping them in the kernel repository was just convenient.
> 
> So I personally don't consider the *location* of the DTS files to be a
> basis for deciding what they really mean.

I'm not talking abou where the DTS files sit, I'm talking about where
the compiled blob sits.  There are a number of options here:
	* built into the firmware
	* loaded by the firmware, say from a separate flash partition
(e.g. modern uboot)
	* generated at runtime by the firmware 
	* built into the kernel's bootwrapper (e.g. cuboot).
	* generated by the bootwrapper at runtime from
firmware information in another format (e.g. paul's proposed res2dt
approach for PReP)

Which method is appropriate depends on the needs of the platform,
including what legacy stuff we need to deal with for the platform.
Then in turn, how hard we should work to make the kernel backwards
compatible with old device tree formats depends on what choice we made
here (for platform specific devices, obviously).

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

^ permalink raw reply

* Re: microblaze: Statically linking device tree blobs into the kernel
From: David Gibson @ 2009-04-28  4:10 UTC (permalink / raw)
  To: John Williams
  Cc: Michal Simek, microblaze-uclinux, Linux Kernel list, linuxppc-dev,
	John Linn
In-Reply-To: <1d3f23370904262124l444bc30dmf4178930f4a2b82f@mail.gmail.com>

On Mon, Apr 27, 2009 at 02:24:42PM +1000, John Williams wrote:
> To MicroBlazers and other interested parties:
> 
> Currently the MicroBlaze kernel boot-time ABI requires r7 to point to
> a valid DTB, whereupon in early kernel setup the DTB is copied to a
> statically allocated 16k memory region inside the kernel. From there
> it is later queried by the platform startup code.
> 
> For simple boot scenarios the ability to statically bind a DTB into
> the kernel image would clearly be useful.  In PPC land, this is
> achieved through the simpleboot bootloader that lives in
> arch/powerpc/boot.  The DTB becomes part of the simpleboot payload,
> and is passed to the kernel through the normal means.
> 
> I'm not convinced duplicating this for MicroBlaze is a good idea, I
> think it would be overkill.  However, the make syntax that PPC uses to
> achieve DTB binding is quite nice:
> 
> $ make simpleImage.<board>
> 
> which binds arch/powerpc/boot/dts/<board>.dts into the boot payload.
> 
> My feeling is that we should make use of the fact that the DTB region
> is statically allocated in the MicroBlaze kernel anyway.  From
> arch/microblaze/kernel/vmlinux.lds.S:
> 
>         . = ALIGN (4) ;
>        _fdt_start = . ; /* place for fdt blob */
>        . = . + 0x4000;
>        _fdt_end = . ;
> 
> and in head.S, the DTB at r7 is copied into place at _fdt_start
> 
> /* save fdt to kernel location */
> /* r7 stores pointer to fdt blob */
>         beqi    r7, no_fdt_arg
>         or      r11, r0, r0 /* incremment */
>         ori     r4, r0, TOPHYS(_fdt_start) /* save bram context */
>         ori     r3, r0, (0x4000 - 4)
> _copy_fdt:
>        <simple copy loop>
> no_fdt_arg:
> 
> Since this memory is already allocated in the kernel image but is
> normally just zeros, to bind a DTB to the kernel we could just store
> it in-situ.  This way, if a non-zero r7 is passed in at boot time,
> head.S will naturally overwrite (and thus override) the "default" DTB
> that was inside the kernel image.
> 
> What I'm not so sure about is how best to achieve this in the kbuild
> sequence.  I see two options:
> 
>  (a) use .incbin in a .S file, similar to how the initramfs gets
> linked in in /usr/Makefile etc, or

Or you could build the .dts directly into a .S file (which dtc
supports) and #include or link that in.  It's possible the dtc asm
output mode would need some work, but that's easily enough done.

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

^ permalink raw reply

* Re: removing get_immrbase()??
From: David Gibson @ 2009-04-28  4:12 UTC (permalink / raw)
  To: Kumar Gala; +Cc: Scott Wood, Linuxppc-dev Development, Timur Tabi
In-Reply-To: <49668C6D-3A6A-499E-A8AD-85B8E808F6CF@kernel.crashing.org>

On Wed, Apr 22, 2009 at 11:41:31PM -0500, Kumar Gala wrote:
>
> On Apr 22, 2009, at 11:06 PM, David Gibson wrote:
>
>> Well, yes, I guess I agree.  How immutable you consider the device
>> tree blob to be is a judgement call based on the specific details of
>> platform/board in question.  If it is indeed a reference platform, in
>> the early stages of development where it's reasonably easy to change
>> the dtb, then it's probably best to change the dtb in sync with the
>> kernel to reduce long-term cruft build-up.  But once the board is
>> sufficiently widely deployed, you want to stop doing that and include
>> backwards compatibility workarounds in the kernel to cope with the
>> widely deployed broken trees.
>
> I disagree with the point about providing workarounds to cope w/deployed 
> device trees (at least for the problems I'm thinking off in which nodes 
> didn't exist).  This just sounds like double work and is a disincentive 
> to actually making such changes.
>
> Lets say I had an error driver for our MCM (core to soc coherency  
> module).  It was getting the base address by using get_immrbase().   
> Today I proposed a proper device node for the MCM block as it doesn't  
> exist in .dts today.  We add such a node into .dts and I can clean up my 
> error driver to use proper device node information.  However I've just 
> broken any old .dts that didn't have this node.  You are saying I need to 
> add code into the kernel to create this new node and we have to keep that 
> code around for ever in the kernel.. why would I ever bother to actually 
> changing anything than.

Well, again.  It's a judgement call, balancing the pain of having to
update the dts files (which depends on how widely deployed the
platform is) versus the pain of having to keep the bacwards
compatibility shim in the kernel.

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

^ permalink raw reply

* Please revert edada399 and 9203fc9c
From: Paul Mackerras @ 2009-04-28  4:56 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linuxppc-dev, linux-kernel, Tim Abbott

Linus,

Please revert commits edada399 ("powerpc: Use TEXT_TEXT macro in
linker script.") and 9203fc9c ("powerpc: Use __REF macro instead of
old .text.init.refok."), which depends on edada399.

Commit edada399 breaks the build because it moves the __ftr_alt_*
sections of a file away from the .text section, causing link failures
due to relative conditional branch targets being too far away from the
branch instructions.  This happens on pretty much all 64-bit powerpc
configs.

Clearly these patches were never even build-tested.  They were never
acked by the powerpc maintainer (Ben) - because he was on vacation -
and they weren't sent to the deputy maintainer (me) or the relevant
mailing list (linuxppc-dev).

And they are clearly not fixes for regressions or serious bugs, so why
are these patches going in after -rc3 anyway?

Paul.

^ permalink raw reply

* Re: "leds: Add openfirmware platform device support" breaks sparc
From: Grant Likely @ 2009-04-28  3:59 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Michal Simek, tpiepho, linuxppc-dev, rpurdie, smaclennan,
	sparclinux, David Miller, John Williams
In-Reply-To: <20090427152051.5067e888.akpm@linux-foundation.org>

On Mon, Apr 27, 2009 at 4:20 PM, Andrew Morton
<akpm@linux-foundation.org> wrote:
> On Tue, 03 Mar 2009 16:37:13 -0800 (PST)
> David Miller <davem@davemloft.net> wrote:
>
>> From: Sean MacLennan <smaclennan@pikatech.com>
>> Date: Tue, 3 Mar 2009 19:29:32 -0500
>>
>> > It has been..... uhhhh carry the two... longer than I want to admit
>> > since I worked on a sparc. Would GPIO based LEDS make sense on a sparc
>> > platform? Is sparc used much in the embedded world?
>> >
>> > If yes, the of_register_platform_driver is just a nice wrapper. It
>> > would be trivial to either change it to work on sparc, or add the
>> > wrapper to the sparc includes.
>>
>> We generally create the platform devices by hand for LED
>> devices on sparc64.
>>
>> I'd CONFIG_POWERPC depend this thing for now.
>
> Nobody has done this, so current mainline's sparc64 allmodconfig remains
> busted.
>
>
> This?
>
> --- a/drivers/leds/Kconfig~a
> +++ a/drivers/leds/Kconfig
> @@ -139,6 +139,7 @@ config LEDS_GPIO_PLATFORM
> =A0config LEDS_GPIO_OF
> =A0 =A0 =A0 =A0bool "OpenFirmware platform device bindings for GPIO LEDs"
> =A0 =A0 =A0 =A0depends on LEDS_GPIO && OF_DEVICE
> + =A0 =A0 =A0 depends on POWERPC
> =A0 =A0 =A0 =A0default y
> =A0 =A0 =A0 =A0help
> =A0 =A0 =A0 =A0 =A0Let the leds-gpio driver drive LEDs which have been de=
fined as


PowerPC actually uses CONFIG_PPC, so this doesn't work.  However, this
might be better:  I've compile tested it on powerpc, but I don't have
microblaze or sparc xcompilers right now.  Also, probably word-wrapped
since I'm pasting it into my mailer, but I wanted to keep this within
the thread.  I'll repost "for real" first thing tomorrow morning.

g.

commit 302d02a46c67938cf4ef310fec90734cb38acabe
Author: Grant Likely <grant.likely@secretlab.ca>
Date:   Mon Apr 27 21:54:35 2009 -0600

    of: make of_(un)register_platform_driver common code.

    Some drivers using of_register_platform_driver() wrapper break on sparc
    because the wrapper isn't in the header file.  This patch moves it from
    Microblaze and PowerPC implementations and makes it common code.

    Signed-off-by: Grant Likely <grant.likely@secretlab.ca>

diff --git a/arch/microblaze/include/asm/of_platform.h
b/arch/microblaze/include/asm/of_platform.h
index 187c0ee..3749127 100644
--- a/arch/microblaze/include/asm/of_platform.h
+++ b/arch/microblaze/include/asm/of_platform.h
@@ -36,16 +36,6 @@ static const struct of_device_id of_default_bus_ids[] =
=3D {
        {},
 };

-/* Platform drivers register/unregister */
-static inline int of_register_platform_driver(struct of_platform_driver *d=
rv)
-{
-       return of_register_driver(drv, &of_platform_bus_type);
-}
-static inline void of_unregister_platform_driver(struct
of_platform_driver *drv)
-{
-       of_unregister_driver(drv);
-}
-
 /* Platform devices and busses creation */
 extern struct of_device *of_platform_device_create(struct device_node *np,
                                                const char *bus_id,
diff --git a/arch/powerpc/include/asm/of_platform.h
b/arch/powerpc/include/asm/of_platform.h
index 53b4650..d4aaa34 100644
--- a/arch/powerpc/include/asm/of_platform.h
+++ b/arch/powerpc/include/asm/of_platform.h
@@ -11,16 +11,6 @@
  *
  */

-/* Platform drivers register/unregister */
-static inline int of_register_platform_driver(struct of_platform_driver *d=
rv)
-{
-       return of_register_driver(drv, &of_platform_bus_type);
-}
-static inline void of_unregister_platform_driver(struct
of_platform_driver *drv)
-{
-       of_unregister_driver(drv);
-}
-
 /* Platform devices and busses creation */
 extern struct of_device *of_platform_device_create(struct device_node *np,
                                                   const char *bus_id,
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h
index 3d327b6..9084066 100644
--- a/include/linux/of_platform.h
+++ b/include/linux/of_platform.h
@@ -51,6 +51,16 @@ extern int of_register_driver(struct of_platform_driver =
*drv,
                              struct bus_type *bus);
 extern void of_unregister_driver(struct of_platform_driver *drv);

+/* Platform drivers register/unregister */
+static inline int of_register_platform_driver(struct of_platform_driver *d=
rv)
+{
+       return of_register_driver(drv, &of_platform_bus_type);
+}
+static inline void of_unregister_platform_driver(struct
of_platform_driver *drv)
+{
+       of_unregister_driver(drv);
+}
+
 #include <asm/of_platform.h>

 extern struct of_device *of_find_device_by_node(struct device_node *np);


--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply related


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