* [patch 23/24] rapidio: add the memory mapping support in rionet driver
From: akpm @ 2008-03-28 21:21 UTC (permalink / raw)
To: paulus; +Cc: akpm, linuxppc-dev
From: Zhang Wei <wei.zhang@freescale.com>
The user can select memory mapping mode or message mode in CONFIG. It is also
an example to how-to use memory mapping driver for RapidIO.
Signed-off-by: Zhang Wei <wei.zhang@freescale.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
drivers/net/Kconfig | 10 +
drivers/net/rionet.c | 324 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 334 insertions(+)
diff -puN drivers/net/Kconfig~rapidio-add-the-memory-mapping-support-in-rionet-driver drivers/net/Kconfig
--- a/drivers/net/Kconfig~rapidio-add-the-memory-mapping-support-in-rionet-driver
+++ a/drivers/net/Kconfig
@@ -2719,6 +2719,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
bool "FDDI driver support"
depends on (PCI || EISA || TC)
diff -puN drivers/net/rionet.c~rapidio-add-the-memory-mapping-support-in-rionet-driver drivers/net/rionet.c
--- a/drivers/net/rionet.c~rapidio-add-the-memory-mapping-support-in-rionet-driver
+++ a/drivers/net/rionet.c
@@ -1,6 +1,13 @@
/*
* rionet - Ethernet driver over RapidIO messaging services
*
+ * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+ * Author: Zhang Wei, wei.zhang@freescale.com, Jun 2007
+ *
+ * Changelog:
+ * Jun 2007 Zhang Wei <wei.zhang@freescale.com>
+ * - Added the support to RapidIO memory driver. 2007.
+ *
* Copyright 2005 MontaVista Software, Inc.
* Matt Porter <mporter@kernel.crashing.org>
*
@@ -8,6 +15,7 @@
* 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.
+ *
*/
#include <linux/module.h>
@@ -23,6 +31,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 +49,47 @@ 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_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 +103,18 @@ 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;
+ struct rio_mem *rxmem;
+ struct rio_mem *txmem;
+#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 +145,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 +164,11 @@ static int rionet_rx_clean(struct net_de
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 +186,7 @@ static int rionet_rx_clean(struct net_de
return i;
}
+#endif
static void rionet_rx_fill(struct net_device *ndev, int end)
{
@@ -141,19 +200,94 @@ static void rionet_rx_fill(struct net_de
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 = ndev->priv;
+ int enqueue, dequeue;
+ int err;
+
+ 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;
+ }
+
+ err = rio_space_find_mem(rnet->mport, rdev->destid, RIONET_DRVID,
+ &rnet->txmem->riores);
+ if (err) {
+ ndev->stats.tx_dropped++;
+ printk(KERN_ERR "Rio find mem err %d\n", err);
+ return -EBUSY;
+ }
+ rio_map_outb_region(rnet->mport, rdev->destid, rnet->txmem, 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->txmem->iores.start,
+ dma_map_single(&ndev->dev, skb->data, skb->len,
+ DMA_TO_DEVICE), skb->len, 0);
+ if (!tx)
+ return -EFAULT;
+ tx->ack = 1;
+ 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->txmem);
+ 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 = ndev->priv;
+#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 +299,19 @@ static int rionet_queue_tx_msg(struct sk
++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 +358,93 @@ static int rionet_start_xmit(struct sk_b
return 0;
}
+#ifdef CONFIG_RIONET_MEMMAP
+static void rio_recv_mem(struct net_device *ndev)
+{
+ struct rionet_private *rnet = (struct rionet_private *)ndev->priv;
+ 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->rxmem->iores.start,
+ size, 0);
+ if (!tx)
+ return;
+ tx->ack = 1;
+ 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 = (struct rionet_private *)ndev->priv;
+ 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 +466,10 @@ static void rionet_dbell_event(struct ri
}
} 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 +477,7 @@ static void rionet_dbell_event(struct ri
}
}
+#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 +520,58 @@ static void rionet_outb_msg_event(struct
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)
{
@@ -299,6 +590,28 @@ static int rionet_open(struct net_device
rionet_dbell_event)) < 0)
goto out;
+#ifdef CONFIG_RIONET_MEMMAP
+ rnet->rxmem = rio_request_inb_region(rnet->mport, NULL,
+ RIONET_TX_RX_BUFF_SIZE, "rionet_rx_buff", RIONET_DRVID);
+ if (!rnet->rxmem) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ rnet->rxbuff = rnet->rxmem->virt;
+
+ rnet->txmem = rio_prepare_io_mem(rnet->mport, NULL,
+ RIONET_TX_RX_BUFF_SIZE, "rionet_tx_buff");
+ if (!rnet->txmem) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ rnet->txbuff = rnet->txmem->virt;
+#ifdef CONFIG_RIONET_DMA
+ rc = rionet_dma_register(rnet);
+ if (rc)
+ goto out;
+#endif /* CONFIG_RIONET_DMA */
+#else
if ((rc = rio_request_inb_mbox(rnet->mport,
(void *)ndev,
RIONET_MAILBOX,
@@ -312,6 +625,7 @@ static int rionet_open(struct net_device
RIONET_TX_RING_SIZE,
rionet_outb_msg_event)) < 0)
goto out;
+#endif
/* Initialize inbound message ring */
for (i = 0; i < RIONET_RX_RING_SIZE; i++)
@@ -375,8 +689,18 @@ static int rionet_close(struct net_devic
rio_release_inb_dbell(rnet->mport, RIONET_DOORBELL_JOIN,
RIONET_DOORBELL_LEAVE);
+#ifdef CONFIG_RIONET_MEMMAP
+ rio_release_inb_region(rnet->mport, rnet->rxmem);
+ rio_release_outb_region(rnet->mport, rnet->txmem);
+ 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;
}
_
^ permalink raw reply
* [patch 18/24] rapidio: add RapidIO space allocation bitmap arithmetic
From: akpm @ 2008-03-28 21:21 UTC (permalink / raw)
To: paulus; +Cc: akpm, linuxppc-dev
From: Zhang Wei <wei.zhang@freescale.com>
The bitmap is the simplest RapidIO space allocation arithmetic. It uses the
fixed size space for each RapidIO device in the inter-connection network.
Signed-off-by: Zhang Wei <wei.zhang@freescale.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
arch/powerpc/sysdev/fsl_rio.c | 11
drivers/rapidio/Kconfig | 2
drivers/rapidio/Makefile | 1
drivers/rapidio/rio.c | 1
drivers/rapidio/sallocator/Kconfig | 9
drivers/rapidio/sallocator/Makefile | 12
drivers/rapidio/sallocator/bitmap.c | 384 ++++++++++++++++++++++++++
include/linux/rio.h | 6
8 files changed, 425 insertions(+), 1 deletion(-)
diff -puN arch/powerpc/sysdev/fsl_rio.c~rapidio-add-rapidio-space-allocation-bitmap-arithmetic arch/powerpc/sysdev/fsl_rio.c
--- a/arch/powerpc/sysdev/fsl_rio.c~rapidio-add-rapidio-space-allocation-bitmap-arithmetic
+++ a/arch/powerpc/sysdev/fsl_rio.c
@@ -920,6 +920,17 @@ static int fsl_rio_doorbell_init(struct
return rc;
}
+u32 rio_get_mport_id(struct rio_mport *mport)
+{
+ u32 mport_id;
+
+ rio_local_read_config_32(mport, 0x60, &mport_id);
+ mport_id = mport->sys_size ? (mport_id & 0xffff) :
+ ((mport_id >> 16) & 0xff);
+ return mport_id;
+
+}
+
static char *cmdline = NULL;
static int fsl_rio_get_hdid(int index)
diff -puN drivers/rapidio/Kconfig~rapidio-add-rapidio-space-allocation-bitmap-arithmetic drivers/rapidio/Kconfig
--- a/drivers/rapidio/Kconfig~rapidio-add-rapidio-space-allocation-bitmap-arithmetic
+++ a/drivers/rapidio/Kconfig
@@ -8,3 +8,5 @@ config RAPIDIO_DISC_TIMEOUT
---help---
Amount of time a discovery node waits for a host to complete
enumeration before giving up.
+
+source "drivers/rapidio/sallocator/Kconfig"
diff -puN drivers/rapidio/Makefile~rapidio-add-rapidio-space-allocation-bitmap-arithmetic drivers/rapidio/Makefile
--- a/drivers/rapidio/Makefile~rapidio-add-rapidio-space-allocation-bitmap-arithmetic
+++ a/drivers/rapidio/Makefile
@@ -4,3 +4,4 @@
obj-y += rio.o rio-access.o rio-driver.o rio-scan.o rio-sysfs.o
obj-$(CONFIG_RAPIDIO) += switches/
+obj-$(CONFIG_RAPIDIO) += sallocator/
diff -puN drivers/rapidio/rio.c~rapidio-add-rapidio-space-allocation-bitmap-arithmetic drivers/rapidio/rio.c
--- a/drivers/rapidio/rio.c~rapidio-add-rapidio-space-allocation-bitmap-arithmetic
+++ a/drivers/rapidio/rio.c
@@ -849,6 +849,7 @@ int rio_init_mports(void)
rio_enum_mport(port);
else
rio_disc_mport(port);
+ rio_space_init(port);
}
out:
diff -puN /dev/null drivers/rapidio/sallocator/Kconfig
--- /dev/null
+++ a/drivers/rapidio/sallocator/Kconfig
@@ -0,0 +1,9 @@
+choice
+ prompt "Default RapidIO Space Allocator"
+ depends on RAPIDIO
+ default RIO_SA_DEFAULT_BITMAP
+
+ config RIO_SA_DEFAULT_BITMAP
+ bool "Bitmap"
+
+endchoice
diff -puN /dev/null drivers/rapidio/sallocator/Makefile
--- /dev/null
+++ a/drivers/rapidio/sallocator/Makefile
@@ -0,0 +1,12 @@
+#
+# Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+#
+# Author: Zhang Wei, wei.zhang@freescale.com, Jun 2007
+#
+# This 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.
+#
+
+obj-$(CONFIG_RIO_SA_DEFAULT_BITMAP) += bitmap.o
diff -puN /dev/null drivers/rapidio/sallocator/bitmap.c
--- /dev/null
+++ a/drivers/rapidio/sallocator/bitmap.c
@@ -0,0 +1,384 @@
+/*
+ * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+ * Author: Zhang Wei, wei.zhang@freescale.com, Jun 2007
+ *
+ * Description:
+ * RapidIO space allocator bitmap arithmetic.
+ *
+ * The Bitmap allocator make the whole RapidIO device have the same fixed
+ * inbound memory window. And on the top of each device inbound window,
+ * there is a sect0 area, which will use for recording the individual
+ * driver owned memory space in device.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/rio.h>
+#include <linux/rio_drv.h>
+#include <linux/rio_ids.h>
+#include <linux/rio_regs.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/seq_file.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/dma-mapping.h>
+
+#include "../rio.h"
+
+#undef DEBUG
+
+#define RIO_SBLOCK_SIZE 4096
+
+#define ERR(fmt, arg...) \
+ printk(KERN_ERR "ERROR %s - %s: " fmt, __FILE__, __func__, ## arg)
+#ifdef DEBUG
+#define DBG(fmt...) printk(fmt)
+#else
+#define DBG(fmt...) do {} while (0)
+#endif
+
+#define IS_64BIT_RES ((sizeof(resource_size_t) == 8) ? 1 : 0)
+#define SA_BITMAP_DRV_ID 0x4249544d
+#define SA_RIO_RESERVE_SPACE 0x4000000
+
+/* Definition for struct rio_res:ctrl */
+#define SA_RIO_RES_CTRL_EN 0x80000000
+struct rio_res {
+ u32 ctrl; /* Control words
+ * Bit 31: Enable bit.
+ */
+ u32 addr; /* The start addr bits [0-31] of RapidIO window */
+ u32 extaddr; /* The start addr bits [32-63] of RapidIO window */
+ u32 size; /* The size bits [0-31] of RapidIO window */
+ u32 extsize; /* The size bits [32-63] of RapidIO window */
+ u32 owner; /* The owner driver id */
+ u32 rev[2]; /* For align 32 bytes */
+};
+
+#define SA_BITMAP_MAX_INB_RES 32
+struct rio_sect0 {
+ u32 id; /* ID for Bitmap space allocater driver */
+ u32 rioid; /* RapidIO device id */
+ u32 width; /* The resource width for RIO space, 32 or 64 */
+ u8 rev1[56]; /* Align to 64 bytes */
+ struct rio_res inb_res[SA_BITMAP_MAX_INB_RES];
+ u8 rev2[4096 - 64 - SA_BITMAP_MAX_INB_RES * 32];
+ /* Fill for 4096 bytes */
+};
+
+/* if select 64bit resource, we can use 34-bit rio address, otherwise 32-bit */
+static int rio_addr_size;
+static struct resource *root;
+static struct rio_mem sect0mem; /* Sect 0 memory data */
+static struct rio_sect0 *sect0;
+static struct rio_mem *sblock_buf;
+
+/**
+ * get_rio_addr_size -- get the RapidIO space address size.
+ *
+ * If it's a 64-bit system, the RapidIO space address size could be 34bit,
+ * otherwise, it should be 32 bit.
+ */
+static inline int get_rio_addr_size(void)
+{
+ return (sizeof(resource_size_t) == 8) ? 34 : 32;
+}
+
+/**
+ * rio_space_request -- request RapidIO space.
+ * @mport: RIO master port.
+ * @size: The request space size, must >= 4096.
+ * @new: The resource which required.
+ *
+ * Return:
+ * 0 -- Success
+ * others -- return from allocate_resource()
+ *
+ * This function request a memory from RapidIO space.
+ */
+int rio_space_request(struct rio_mport *mport, resource_size_t size,
+ struct resource *new)
+{
+ int ret = 0;
+
+ /* Align the size to 2^N */
+ size = (size < 0x1000) ? 0x1000 : 1 << (__ilog2(size - 1) + 1);
+
+ memset(new, 0, sizeof(struct resource));
+
+ ret = allocate_resource(root, new, size, root->start, root->end,
+ size, NULL, 0);
+ return ret;
+}
+
+#ifdef DEBUG
+/**
+ * rio_sa_dump_sect0 -- Dump the sect0 content.
+ * @psect0: The point of sect0
+ */
+static void rio_sa_dump_sect0(struct rio_sect0 *psect0)
+{
+ int i;
+
+ if (!psect0)
+ return;
+
+ printk(KERN_DEBUG "Rio Sect0 %p dump:\n", psect0);
+ printk(KERN_DEBUG "...id = 0x%08x, width = %d, rioid = %d\n",
+ psect0->id, psect0->width, psect0->rioid);
+ for (i = 0; i < SA_BITMAP_MAX_INB_RES; i++)
+ if (psect0->inb_res[i].ctrl & SA_RIO_RES_CTRL_EN)
+ printk(KERN_DEBUG
+ "...inb_res[%d]: ctrl 0x%08x, owner 0x%08x\n"
+ "\t\textaddr 0x%08x, addr 0x%08x\n"
+ "\t\textsize 0x%08x, size 0x%08x\n", i,
+ psect0->inb_res[i].ctrl,
+ psect0->inb_res[i].owner,
+ psect0->inb_res[i].extaddr,
+ psect0->inb_res[i].addr,
+ psect0->inb_res[i].extsize,
+ psect0->inb_res[i].size);
+}
+#endif
+
+/**
+ * rio_space_claim -- Claim the memory in RapidIO space
+ * @mem: The memory should be claimed.
+ *
+ * When you get a memory space and get ready of it, you should claim it in
+ * RapidIO space. Then, the other device could get the memory by calling
+ * rio_space_find_mem().
+ */
+int rio_space_claim(struct rio_mem *mem)
+{
+ int i;
+
+ if (!sect0) {
+ ERR("Sect0 is NULL!\n");
+ return -EFAULT;
+ }
+#ifdef DEBUG
+ rio_sa_dump_sect0(sect0);
+#endif
+
+ for (i = 0; i < SA_BITMAP_MAX_INB_RES; i++)
+ if (!(sect0->inb_res[i].ctrl & SA_RIO_RES_CTRL_EN)) {
+ sect0->inb_res[i].ctrl |= SA_RIO_RES_CTRL_EN;
+ sect0->inb_res[i].addr = (u32)(mem->riores.start);
+ sect0->inb_res[i].size = (u32)(mem->riores.end
+ - mem->riores.start + 1);
+ if (IS_64BIT_RES) {
+ sect0->inb_res[i].extaddr =
+ (u64)mem->riores.start >> 32;
+ sect0->inb_res[i].extsize =
+ (u64)(mem->riores.end
+ - mem->riores.start + 1) >> 32;
+ }
+ sect0->inb_res[i].owner = mem->owner;
+ DBG("The new inbound rio mem added:\n");
+ DBG("...inb_res[%d]: ctrl 0x%08x, owner 0x%08x\n"
+ "\t\textaddr 0x%08x, addr 0x%08x\n"
+ "\t\textsize 0x%08x, size 0x%08x\n", i,
+ sect0->inb_res[i].ctrl,
+ sect0->inb_res[i].owner,
+ sect0->inb_res[i].extaddr,
+ sect0->inb_res[i].addr,
+ sect0->inb_res[i].extsize,
+ sect0->inb_res[i].size);
+ return 0;
+ }
+
+ ERR("No free inbound window!\n");
+ return -EBUSY;
+}
+
+/**
+ * rio_space_release -- remove the memory record from RapidIO space.
+ * It's the pair function of rio_space_claim().
+ *
+ * @inbmem: The memory should be release.
+ */
+void rio_space_release(struct rio_mem *inbmem)
+{
+ int i;
+
+ /* Remove it from sect0 inb_res array */
+ for (i = 0; i < SA_BITMAP_MAX_INB_RES; i++)
+ if ((sect0->inb_res[i].ctrl & SA_RIO_RES_CTRL_EN) &&
+ (((u64)sect0->inb_res[i].extaddr << 32 |
+ sect0->inb_res[i].addr)
+ == (u64)inbmem->riores.start)) {
+ sect0->inb_res[i].ctrl = 0;
+ sect0->inb_res[i].addr = 0;
+ sect0->inb_res[i].extaddr = 0;
+ sect0->inb_res[i].size = 0;
+ sect0->inb_res[i].extsize = 0;
+ }
+}
+
+/**
+ * rio_space_get_dev_mem -- get the whole owned inbound space of
+ * RapidIO device with did.
+ */
+static int rio_space_get_dev_mem(struct rio_mport *mport,
+ u16 did, struct resource *res)
+{
+ if (!res)
+ return -EINVAL;
+
+ res->start = SA_RIO_RESERVE_SPACE + (did
+ << (rio_addr_size - __ilog2(RIO_ANY_DESTID(mport->sys_size)
+ + 1)));
+ res->end = res->start +
+ (1 << (rio_addr_size - __ilog2(RIO_ANY_DESTID(mport->sys_size)
+ + 1))) - 1;
+ res->flags = RIO_RESOURCE_MEM;
+
+ return 0;
+}
+
+/**
+ * rio_space_find_mem -- Find the memory space (RIO) of the rio driver owned.
+ * @mport: RIO master port.
+ * @tid: The target RapidIO device id which will be searched.
+ * @owner: The driver id as the search keyword.
+ * @res: The result of finding.
+ *
+ * return:
+ * 0 -- Success
+ * -EFAULT -- Remote sect0 is a bad address
+ * -EPROTONOSUPPORT -- The remote space allocator protocol is not support
+ *
+ * This function will find the memory located in RapidIO space, which is owned
+ * by the driver. If the remote RapidIO device use the diffrent space allocator,
+ * it will return -EPROTONOSUPPORT.
+ */
+int rio_space_find_mem(struct rio_mport *mport, u16 tid,
+ u32 owner, struct resource *res)
+{
+ struct rio_sect0 __iomem *rsect0;
+ int i;
+ int ret = 0;
+ u32 width;
+
+ ret = rio_space_get_dev_mem(mport, tid, &sblock_buf->riores);
+ if (ret) {
+ ERR("Rio space get dev memory err!\n");
+ goto out;
+ }
+ sblock_buf->size = RIO_SBLOCK_SIZE;
+ rio_map_outb_region(mport, tid, sblock_buf, 0);
+
+ if (!sblock_buf->virt) {
+ ERR("Sect0 block buffer is NULL!\n");
+ ret = -EFAULT;
+ goto out;
+ }
+ rsect0 = sblock_buf->virt;
+
+ if (in_be32(&rsect0->id) != SA_BITMAP_DRV_ID) {
+ DBG("The target RapidIO space allocator is not rio_sa_bitmap! "
+ "id = 0x%x\n", rsect0->id);
+ ret = -EPROTONOSUPPORT;
+ goto out;
+ }
+
+#ifdef DEBUG
+ /* Dump remote sect0 for debug */
+ DBG("Dump the remote RIO dev %d sect0\n", tid);
+ rio_sa_dump_sect0(rsect0);
+#endif
+
+ width = in_be32(&rsect0->width);
+ if (sizeof(resource_size_t) * 8 < width)
+ printk(KERN_WARNING "WARNING: The system width %d is smaller "
+ "than the remote RapidIO space address width %d!",
+ sizeof(resource_size_t) * 8, width);
+
+ /* Find the rio space block */
+ for (i = 0; i < SA_BITMAP_MAX_INB_RES; i++)
+ if ((in_be32(&rsect0->inb_res[i].ctrl) & SA_RIO_RES_CTRL_EN)
+ && (in_be32(&rsect0->inb_res[i].owner) == owner)) {
+ if (!res) {
+ ERR("Resource NULL error!\n");
+ ret = -EFAULT;
+ goto out;
+ }
+ memset(res, 0, sizeof(struct resource));
+ res->start = (IS_64BIT_RES && (width > 32)) ?
+ in_be32(&rsect0->inb_res[i].extaddr) << 32 : 0
+ | rsect0->inb_res[i].addr;
+ res->end = res->start - 1 +
+ ((in_be32(&rsect0->inb_res[i].size)) |
+ ((IS_64BIT_RES && (width > 32)) ?
+ ((u64)(in_be32(&rsect0->inb_res[i].extsize))
+ << 32) : 0));
+ goto out;
+ }
+
+out:
+ rio_unmap_outb_region(mport, sblock_buf);
+ return ret;
+}
+
+/**
+ * rio_space_init -- RapidIO space allocator initialization function.
+ * @mport: The master port.
+ */
+int rio_space_init(struct rio_mport *mport)
+{
+ int rc;
+
+ root = &mport->riores[RIO_INB_MEM_RESOURCE];
+ memset(root, 0, sizeof(struct resource));
+
+ rio_addr_size = get_rio_addr_size();
+
+ rc = rio_space_get_dev_mem(mport, rio_get_mport_id(mport), root);
+ if (rc) {
+ ERR("bitmap: get rio dev memory err, rc = %d\n", rc);
+ return rc;
+ }
+ root->name = "rio_space_inb";
+
+ /* Alloc the sect 0 for space managerment */
+ memset(§0mem, 0, sizeof(struct rio_mem));
+ sect0mem.virt = dma_alloc_coherent(NULL, RIO_SBLOCK_SIZE,
+ §0mem.iores.start, GFP_KERNEL);
+ if (!sect0mem.virt)
+ return -ENOMEM;
+
+ sect0mem.iores.end = sect0mem.iores.start + RIO_SBLOCK_SIZE - 1;
+ sect0mem.size = RIO_SBLOCK_SIZE;
+
+ if (rio_space_request(mport, RIO_SBLOCK_SIZE, §0mem.riores))
+ return -ENOMEM;
+
+ sect0mem.riores.name = "sect 0";
+ sect0 = sect0mem.virt;
+ sect0->id = SA_BITMAP_DRV_ID;
+ sect0->rioid = rio_get_mport_id(mport);
+ sect0->width = rio_addr_size;
+
+ /* map outbond window to access rio inb */
+ rio_map_inb_region(mport, §0mem, 0);
+
+ /* Init sblock buffer for block seeking */
+ sblock_buf = rio_prepare_io_mem(mport, NULL, RIO_SBLOCK_SIZE,
+ "sblock_buf");
+ if (!sblock_buf)
+ return -ENOMEM;
+
+ return 0;
+}
diff -puN include/linux/rio.h~rapidio-add-rapidio-space-allocation-bitmap-arithmetic include/linux/rio.h
--- a/include/linux/rio.h~rapidio-add-rapidio-space-allocation-bitmap-arithmetic
+++ a/include/linux/rio.h
@@ -60,11 +60,15 @@
*
* 0 RapidIO inbound doorbells
* 1 RapidIO inbound mailboxes
- * 1 RapidIO outbound mailboxes
+ * 2 RapidIO outbound mailboxes
+ * 3 RapidIO inbound memory
+ * 4 RapidIO outbound memory
*/
#define RIO_DOORBELL_RESOURCE 0
#define RIO_INB_MBOX_RESOURCE 1
#define RIO_OUTB_MBOX_RESOURCE 2
+#define RIO_INB_MEM_RESOURCE 3
+#define RIO_OUTB_MEM_RESOURCE 4
extern struct bus_type rio_bus_type;
extern struct list_head rio_devices; /* list of all devices */
_
^ permalink raw reply
* [patch 17/24] rapidio: add memory mapping driver to RapidIO
From: akpm @ 2008-03-28 21:21 UTC (permalink / raw)
To: paulus; +Cc: akpm, linuxppc-dev
From: Zhang Wei <wei.zhang@freescale.com>
The memory mapping driver is used for mapping IO address and system memory
address space to RapidIO address space. The driver support IO space
allocation, RapidIO space inbound window and outbound window creation. The
system can access other RapidIO device by outbound window and can be accessed
by other RapidIO device through inbound window.
Signed-off-by: Zhang Wei <wei.zhang@freescale.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
arch/powerpc/sysdev/fsl_rio.c | 4
drivers/rapidio/rio.c | 362 ++++++++++++++++++++++++++++++++
include/linux/rio.h | 39 +++
include/linux/rio_drv.h | 41 +++
4 files changed, 440 insertions(+), 6 deletions(-)
diff -puN arch/powerpc/sysdev/fsl_rio.c~rapidio-add-memory-mapping-driver-to-rapidio arch/powerpc/sysdev/fsl_rio.c
--- a/arch/powerpc/sysdev/fsl_rio.c~rapidio-add-memory-mapping-driver-to-rapidio
+++ a/arch/powerpc/sysdev/fsl_rio.c
@@ -1058,6 +1058,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) {
@@ -1068,8 +1069,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);
diff -puN drivers/rapidio/rio.c~rapidio-add-memory-mapping-driver-to-rapidio drivers/rapidio/rio.c
--- a/drivers/rapidio/rio.c~rapidio-add-memory-mapping-driver-to-rapidio
+++ a/drivers/rapidio/rio.c
@@ -2,9 +2,16 @@
* RapidIO interconnect services
* (RapidIO Interconnect Specification, http://www.rapidio.org)
*
+ * Copyright (C) 2007 Freescale Semiconductor, Inc.
+ * Author: Zhang Wei, wei.zhang@freescale.com, Jun 2007
+ *
* Copyright 2005 MontaVista Software, Inc.
* Matt Porter <mporter@kernel.crashing.org>
*
+ * Changelog:
+ * Jun 2007 Zhang Wei <wei.zhang@freescale.com>
+ * - Add memory mapping support.
+ *
* 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
@@ -24,10 +31,16 @@
#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 LIST_HEAD(rio_inb_mems);
+static LIST_HEAD(rio_outb_mems);
+
+static DEFINE_SPINLOCK(rio_config_lock);
/**
* rio_local_get_device_id - Get the base/extended device id for a port
@@ -333,6 +346,355 @@ int rio_release_outb_dbell(struct rio_de
}
/**
+ * rio_request_io_region - request resource in RapidIO IO region
+ * @mport: Master port
+ * @res: Resource need be requested.
+ *
+ * Return: 0 - Successed.
+ */
+int rio_request_io_region(struct rio_mport *mport, struct resource *res)
+{
+ if (!res)
+ return -EINVAL;
+
+ return request_resource(&mport->iores, res);
+}
+EXPORT_SYMBOL_GPL(rio_request_io_region);
+
+/**
+ * rio_alloc_io - Allocat IO resource for RapidIO master port.
+ * @mport: Master port
+ * @size: IO resource size
+ * @name: Resource name
+ * @flag: Flag for resource
+ * @res: Return resource which has been allocated.
+ */
+int rio_alloc_io(struct rio_mport *mport, resource_size_t size,
+ const char *name, unsigned long flags, struct resource *res)
+{
+ if (!res)
+ return -EINVAL;
+
+ size = (size < 0x1000) ? 0x1000 : 1 << (__ilog2(size - 1) + 1);
+
+ if (allocate_resource(&mport->iores, res, size, mport->iores.start,
+ mport->iores.end, size, NULL, NULL) < 0) {
+ dev_err(mport->dev, "allocte IO error, no enough space!\n");
+ return -ENOSPC;
+ }
+ res->name = name;
+ res->flags = flags;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rio_alloc_io);
+
+/**
+ * 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 the mem->riores to mem->iores.
+ */
+int rio_map_inb_region(struct rio_mport *mport, struct rio_mem *mem, 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, mem->iores.start, mem->riores.start,
+ mem->size, 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 the mem->iores to mem->riores.
+ */
+int rio_map_outb_region(struct rio_mport *mport, u16 tid,
+ struct rio_mem *mem, 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, mem->iores.start, mem->riores.start,
+ mem->size, 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, struct rio_mem *mem)
+{
+ unsigned long flags;
+ if (!mport->mops)
+ return;
+ spin_lock_irqsave(&rio_config_lock, flags);
+ mport->mops->unmap_inb(mport, mem->iores.start);
+ 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, struct rio_mem *mem)
+{
+ unsigned long flags;
+ if (!mport->mops)
+ return;
+ spin_lock_irqsave(&rio_config_lock, flags);
+ mport->mops->unmap_outb(mport, mem->iores.start);
+ spin_unlock_irqrestore(&rio_config_lock, flags);
+}
+
+/**
+ * rio_release_inb_region -- Release the inbound region resource.
+ * @mport: Master port
+ * @mem: Inbound region descriptor
+ *
+ * Return 0 is successed.
+ */
+int rio_release_inb_region(struct rio_mport *mport, struct rio_mem *mem)
+{
+ int rc = 0;
+ if (!mem)
+ return rc;
+ rio_unmap_inb_region(mport, mem);
+ if (mem->virt)
+ dma_free_coherent(NULL, mem->size, mem->virt, mem->iores.start);
+
+ if (mem->iores.parent)
+ rc = release_resource(&mem->iores);
+ if (mem->riores.parent && !rc)
+ rc = release_resource(&mem->riores);
+
+ if (mem->node.prev)
+ list_del(&mem->node);
+
+ kfree(mem);
+
+ return rc;
+}
+
+/**
+ * rio_request_inb_region -- Request inbound memory region
+ * @mport: Master port
+ * @dev_id: Device specific pointer to pass
+ * @size: The request memory windows size
+ * @name: The region name
+ * @owner: The region owner driver id
+ *
+ * Retrun: The rio_mem struction for inbound memory descriptor.
+ *
+ * This function is used for request RapidIO space inbound region. If the size
+ * less than 4096 or not aligned to 2^N, it will be adjusted. The function will
+ * alloc a block of local DMA memory of the size for inbound region target and
+ * request a RapidIO region for inbound region source. Then the inbound region
+ * will be claimed in RapidIO space and the local DMA memory will be added to
+ * local inbound memory list. The rio_mem with the inbound relationship will
+ * be returned.
+ */
+struct rio_mem *rio_request_inb_region(struct rio_mport *mport, void *dev_id,
+ resource_size_t size, const char *name, u32 owner)
+{
+ struct rio_mem *rmem = NULL;
+ struct rio_dev *dev = dev_id;
+ int ret;
+
+ rmem = kzalloc(sizeof(struct rio_mem), GFP_KERNEL);
+ if (!rmem)
+ goto err;
+
+ /* Align the size to 2^N */
+ size = (size < 0x1000) ? 0x1000 : 1 << (__ilog2(size - 1) + 1);
+
+ /* Alloc the RapidIO space */
+ ret = rio_space_request(mport, size, &rmem->riores);
+ if (ret) {
+ dev_err(mport->dev, "RIO space request error! ret = %d\n", ret);
+ goto err;
+ }
+
+ rmem->dev = dev;
+ rmem->riores.name = name;
+ rmem->size = rmem->riores.end - rmem->riores.start + 1;
+
+ /* Initialize inbound memory */
+ rmem->virt = dma_alloc_coherent(NULL, rmem->size, &rmem->iores.start,
+ GFP_KERNEL);
+ if (!rmem->virt) {
+ dev_err(mport->dev, "Inbound memory alloc error\n");
+ goto err;
+ }
+ rmem->iores.end = rmem->iores.start + rmem->size - 1;
+ rmem->owner = owner;
+
+ /* Map RIO space to local DMA memory */
+ ret = rio_map_inb_region(mport, rmem, 0);
+ if (ret) {
+ dev_err(mport->dev, "RIO map inbound mem error, ret = %d\n",
+ ret);
+ goto err;
+ }
+
+ /* Claim the region */
+ ret = rio_space_claim(rmem);
+ if (ret) {
+ dev_err(mport->dev, "RIO inbound mem claim error, ret = %d\n",
+ ret);
+ goto err;
+ }
+ list_add(&rmem->node, &rio_inb_mems);
+
+ return rmem;
+
+err:
+ rio_release_inb_region(mport, rmem);
+ return NULL;
+}
+
+/**
+ * rio_release_outb_region -- Release the outbound region resource.
+ * @mport: Master port
+ * @mem: Outbound region descriptor
+ *
+ * Return 0 is successed.
+ */
+int rio_release_outb_region(struct rio_mport *mport, struct rio_mem *mem)
+{
+ int rc = 0;
+ if (!mem)
+ return rc;
+ rio_unmap_outb_region(mport, mem);
+ rio_space_release(mem);
+ if (mem->virt)
+ iounmap(mem->virt);
+
+ if (mem->iores.parent)
+ rc = release_resource(&mem->iores);
+ if (mem->riores.parent && !rc)
+ rc = release_resource(&mem->riores);
+
+ if (mem->node.prev)
+ list_del(&mem->node);
+
+ kfree(mem);
+
+ return rc;
+}
+
+/** rio_prepare_io_mem -- Prepare IO region for RapidIO outbound mapping
+ * @mport: Master port
+ * @dev: RIO device specific pointer to pass
+ * @size: Request IO size
+ * @name: The request IO resource name
+ *
+ * Return: The rio_mem descriptor with IO region resource.
+ *
+ * This function request IO region firstly and ioremap it for preparing
+ * outbound window mapping. The function do not map the outbound region
+ * because ioremap can not located at the interrupt action function.
+ * The function can be called in the initialization for just prepared.
+ */
+struct rio_mem *rio_prepare_io_mem(struct rio_mport *mport,
+ struct rio_dev *dev, resource_size_t size, const char *name)
+{
+ struct rio_mem *rmem = NULL;
+ int rc;
+
+ rmem = kzalloc(sizeof(struct rio_mem), GFP_KERNEL);
+ if (!rmem)
+ goto err;
+
+ /* Align the size to 2^N */
+ size = (size < 0x1000) ? 0x1000 : 1 << (__ilog2(size - 1) + 1);
+
+ /* Request RapidIO IO region */
+ rc = rio_alloc_io(mport, size, name, RIO_RESOURCE_MEM, &rmem->iores);
+ if (rc) {
+ dev_err(mport->dev,
+ "RIO io region request error with rc = %d!\n", rc);
+ goto err;
+ }
+
+ rmem->virt = ioremap((phys_addr_t)(rmem->iores.start), size);
+ rmem->size = size;
+ rmem->dev = dev;
+
+ list_add(&rmem->node, &rio_outb_mems);
+ return rmem;
+err:
+ rio_release_outb_region(mport, rmem);
+ return NULL;
+}
+
+/** rio_request_outb_region -- Request IO region and get outbound region
+ * for RapidIO outbound mapping
+ * @mport: Master port
+ * @dev_id: RIO device specific pointer to pass
+ * @size: Request IO size
+ * @name: The request IO resource name
+ * @owner: The outbound region owned driver
+ *
+ * Return: The rio_mem descriptor with IO region resource.
+ *
+ * This function request IO region firstly and ioremap it for preparing
+ * outbound window mapping. And it will find the RapidIO region owned by
+ * the driver id. Then map it. Be careful about that the ioremap can not
+ * be called in the interrupt event action function.
+ */
+struct rio_mem *rio_request_outb_region(struct rio_mport *mport, void *dev_id,
+ resource_size_t size, const char *name, u32 owner)
+{
+ struct rio_mem *rmem = NULL;
+ struct rio_dev *dev = dev_id;
+
+ if (!dev)
+ goto err;
+
+ rmem = rio_prepare_io_mem(mport, dev, size, name);
+ if (!rmem)
+ goto err;
+
+ if (rio_space_find_mem(mport, dev->destid, owner, &rmem->riores)) {
+ dev_err(mport->dev,
+ "Can not find RIO region meet the ownerid %x\n", owner);
+ goto err;
+ }
+
+ /* Map the rio space to local */
+ if (rio_map_outb_region(mport, dev->destid, rmem, 0)) {
+ dev_err(mport->dev, "RIO map outb error!\n");
+ goto err;
+ }
+ return rmem;
+err:
+ rio_release_outb_region(mport, rmem);
+ return NULL;
+}
+
+/**
* 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 -puN include/linux/rio.h~rapidio-add-memory-mapping-driver-to-rapidio include/linux/rio.h
--- a/include/linux/rio.h~rapidio-add-memory-mapping-driver-to-rapidio
+++ a/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,43 @@ struct rio_route_ops {
u16 table, u16 route_destid, u8 * route_port);
};
+/**
+ * Struct for RIO memory definition.
+ * @node: Node in list of memories
+ * @virt: The virtual address for mapped memory accessing.
+ * @owner: The owner id of this memory.
+ * @size: The size of memory space, it should same to iores and riores.
+ * @iores: The resource of local IO region for mapping.
+ * @riores: The resource of mapped RapidIO space region.
+ */
+struct rio_mem {
+ struct list_head node;
+ void *virt;
+ u32 owner;
+ struct rio_dev *dev;
+ resource_size_t size;
+ struct resource iores;
+ struct resource riores;
+};
+
+/**
+ * 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 *, resource_size_t lstart,
+ resource_size_t rstart,
+ resource_size_t size, u32 flags);
+ int (*map_outb) (struct rio_mport *, resource_size_t lstart,
+ resource_size_t rstart,
+ resource_size_t size, u16 tid, u32 flags);
+ void (*unmap_inb) (struct rio_mport *, resource_size_t lstart);
+ void (*unmap_outb) (struct rio_mport *, resource_size_t lstart);
+};
+
/* Architecture and hardware-specific functions */
extern int rio_init_mports(void);
extern void rio_register_mport(struct rio_mport *);
diff -puN include/linux/rio_drv.h~rapidio-add-memory-mapping-driver-to-rapidio include/linux/rio_drv.h
--- a/include/linux/rio_drv.h~rapidio-add-memory-mapping-driver-to-rapidio
+++ a/include/linux/rio_drv.h
@@ -334,6 +334,16 @@ static inline void rio_init_dbell_res(st
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
@@ -408,13 +418,33 @@ extern int rio_request_inb_dbell(struct
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 *);
+extern int rio_request_io_region(struct rio_mport *, struct resource *);
+extern int rio_alloc_io(struct rio_mport *mport, resource_size_t size,
+ const char *name, unsigned long flags, struct resource *res);
+extern struct rio_mem *rio_prepare_io_mem(struct rio_mport *, struct rio_dev *,
+ resource_size_t, const char *);
/* 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);
+extern struct rio_mem *rio_request_inb_region(struct rio_mport *, void *,
+ resource_size_t, const char *, u32);
+extern struct rio_mem *rio_request_outb_region(struct rio_mport *,
+ void *, resource_size_t, const char *, u32);
+extern int rio_release_inb_region(struct rio_mport *, struct rio_mem *);
+extern int rio_release_outb_region(struct rio_mport *, struct rio_mem *);
+
+/* Memory low-level mapping functions */
+extern int rio_map_inb_region(struct rio_mport *, struct rio_mem *, u32);
+extern int rio_map_outb_region(struct rio_mport *, u16, struct rio_mem *, u32);
+extern void rio_unmap_inb_region(struct rio_mport *, struct rio_mem *);
+extern void rio_unmap_outb_region(struct rio_mport *, struct rio_mem *);
+
+/* Memory Allocator */
+extern int rio_space_request(struct rio_mport *, resource_size_t,
+ struct resource *);
+extern int rio_space_find_mem(struct rio_mport *, u16, u32, struct resource *);
+extern int rio_space_init(struct rio_mport *);
+extern int rio_space_claim(struct rio_mem *);
+extern void rio_space_release(struct rio_mem *);
/* LDM support */
int rio_register_driver(struct rio_driver *);
@@ -464,6 +494,7 @@ extern u16 rio_local_get_device_id(struc
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 /* __KERNEL__ */
#endif /* LINUX_RIO_DRV_H */
_
^ permalink raw reply
* [patch 10/24] rapidio: add RapidIO multi mport support
From: akpm @ 2008-03-28 21:21 UTC (permalink / raw)
To: paulus; +Cc: akpm, linuxppc-dev
From: Zhang Wei <wei.zhang@freescale.com>
The original RapidIO driver suppose there is only one mpc85xx RIO controller
in system. So, some data structures are defined as mpc85xx_rio global, such
as 'regs_win', 'dbell_ring', 'msg_tx_ring'. Now, I changed them to mport's
private members. And you can define multi RIO OF-nodes in dts file for multi
RapidIO controller in one processor, such as PCI/PCI-Ex host controllers in
Freescale's silicon. And the mport operation function declaration should be
changed to know which RapidIO controller is target.
Signed-off-by: Zhang Wei <wei.zhang@freescale.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
arch/powerpc/sysdev/fsl_rio.c | 393 +++++++++++++++++---------------
drivers/rapidio/rio-access.c | 10
include/linux/rio.h | 18 -
3 files changed, 237 insertions(+), 184 deletions(-)
diff -puN arch/powerpc/sysdev/fsl_rio.c~rapidio-add-rapidio-multi-mport-support arch/powerpc/sysdev/fsl_rio.c
--- a/arch/powerpc/sysdev/fsl_rio.c~rapidio-add-rapidio-multi-mport-support
+++ a/arch/powerpc/sysdev/fsl_rio.c
@@ -1,6 +1,9 @@
/*
* Freescale MPC85xx/MPC86xx RapidIO support
*
+ * Copyright (C) 2007, 2008 Freescale Semiconductor, Inc.
+ * Zhang Wei <wei.zhang@freescale.com>
+ *
* Copyright 2005 MontaVista Software, Inc.
* Matt Porter <mporter@kernel.crashing.org>
*
@@ -20,6 +23,11 @@
#include <asm/io.h>
+/* RapidIO definition irq, which read from OF-tree */
+#define IRQ_RIO_BELL(m) (((struct rio_priv *)(m->priv))->bellirq)
+#define IRQ_RIO_TX(m) (((struct rio_priv *)(m->priv))->txirq)
+#define IRQ_RIO_RX(m) (((struct rio_priv *)(m->priv))->rxirq)
+
#define RIO_REGS_BASE (CCSRBAR + 0xc0000)
#define RIO_ATMU_REGS_OFFSET 0x10c00
#define RIO_MSG_REGS_OFFSET 0x11000
@@ -112,20 +120,12 @@ struct rio_tx_desc {
u32 res4;
};
-static u32 regs_win;
-static struct rio_atmu_regs *atmu_regs;
-static struct rio_atmu_regs *maint_atmu_regs;
-static struct rio_atmu_regs *dbell_atmu_regs;
-static u32 dbell_win;
-static u32 maint_win;
-static struct rio_msg_regs *msg_regs;
-
-static struct rio_dbell_ring {
+struct rio_dbell_ring {
void *virt;
dma_addr_t phys;
-} dbell_ring;
+};
-static struct rio_msg_tx_ring {
+struct rio_msg_tx_ring {
void *virt;
dma_addr_t phys;
void *virt_buffer[RIO_MAX_TX_RING_SIZE];
@@ -133,16 +133,32 @@ static struct rio_msg_tx_ring {
int tx_slot;
int size;
void *dev_id;
-} msg_tx_ring;
+};
-static struct rio_msg_rx_ring {
+struct rio_msg_rx_ring {
void *virt;
dma_addr_t phys;
void *virt_buffer[RIO_MAX_RX_RING_SIZE];
int rx_slot;
int size;
void *dev_id;
-} msg_rx_ring;
+};
+
+struct rio_priv {
+ void __iomem *regs_win;
+ struct rio_atmu_regs __iomem *atmu_regs;
+ struct rio_atmu_regs __iomem *maint_atmu_regs;
+ struct rio_atmu_regs __iomem *dbell_atmu_regs;
+ void __iomem *dbell_win;
+ void __iomem *maint_win;
+ struct rio_msg_regs __iomem *msg_regs;
+ struct rio_dbell_ring dbell_ring;
+ struct rio_msg_tx_ring msg_tx_ring;
+ struct rio_msg_rx_ring msg_rx_ring;
+ int bellirq;
+ int txirq;
+ int rxirq;
+};
/**
* fsl_rio_doorbell_send - Send a MPC85xx doorbell message
@@ -153,12 +169,14 @@ static struct rio_msg_rx_ring {
* Sends a MPC85xx doorbell message. Returns %0 on success or
* %-EINVAL on failure.
*/
-static int fsl_rio_doorbell_send(int index, u16 destid, u16 data)
+static int fsl_rio_doorbell_send(struct rio_mport *mport,
+ int index, u16 destid, u16 data)
{
+ struct rio_priv *priv = mport->priv;
pr_debug("fsl_doorbell_send: index %d destid %4.4x data %4.4x\n",
index, destid, data);
- out_be32((void *)&dbell_atmu_regs->rowtar, destid << 22);
- out_be16((void *)(dbell_win), data);
+ out_be32(&priv->dbell_atmu_regs->rowtar, destid << 22);
+ out_be16(priv->dbell_win, data);
return 0;
}
@@ -173,11 +191,13 @@ static int fsl_rio_doorbell_send(int ind
* Generates a MPC85xx local configuration space read. Returns %0 on
* success or %-EINVAL on failure.
*/
-static int fsl_local_config_read(int index, u32 offset, int len, u32 *data)
+static int fsl_local_config_read(struct rio_mport *mport,
+ int index, u32 offset, int len, u32 *data)
{
+ struct rio_priv *priv = mport->priv;
pr_debug("fsl_local_config_read: index %d offset %8.8x\n", index,
offset);
- *data = in_be32((void *)(regs_win + offset));
+ *data = in_be32(priv->regs_win + offset);
return 0;
}
@@ -192,12 +212,14 @@ static int fsl_local_config_read(int ind
* Generates a MPC85xx local configuration space write. Returns %0 on
* success or %-EINVAL on failure.
*/
-static int fsl_local_config_write(int index, u32 offset, int len, u32 data)
+static int fsl_local_config_write(struct rio_mport *mport,
+ int index, u32 offset, int len, u32 data)
{
+ struct rio_priv *priv = mport->priv;
pr_debug
("fsl_local_config_write: index %d offset %8.8x data %8.8x\n",
index, offset, data);
- out_be32((void *)(regs_win + offset), data);
+ out_be32(priv->regs_win + offset, data);
return 0;
}
@@ -215,18 +237,19 @@ static int fsl_local_config_write(int in
* success or %-EINVAL on failure.
*/
static int
-fsl_rio_config_read(int index, u16 destid, u8 hopcount, u32 offset, int len,
- u32 * val)
+fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid,
+ u8 hopcount, u32 offset, int len, u32 *val)
{
+ struct rio_priv *priv = mport->priv;
u8 *data;
pr_debug
("fsl_rio_config_read: index %d destid %d hopcount %d offset %8.8x len %d\n",
index, destid, hopcount, offset, len);
- out_be32((void *)&maint_atmu_regs->rowtar,
+ out_be32(&priv->maint_atmu_regs->rowtar,
(destid << 22) | (hopcount << 12) | ((offset & ~0x3) >> 9));
- data = (u8 *) maint_win + offset;
+ data = (u8 *) priv->maint_win + offset;
switch (len) {
case 1:
*val = in_8((u8 *) data);
@@ -255,17 +278,18 @@ fsl_rio_config_read(int index, u16 desti
* success or %-EINVAL on failure.
*/
static int
-fsl_rio_config_write(int index, u16 destid, u8 hopcount, u32 offset,
- int len, u32 val)
+fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid,
+ u8 hopcount, u32 offset, int len, u32 val)
{
+ struct rio_priv *priv = mport->priv;
u8 *data;
pr_debug
("fsl_rio_config_write: index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n",
index, destid, hopcount, offset, len, val);
- out_be32((void *)&maint_atmu_regs->rowtar,
+ out_be32(&priv->maint_atmu_regs->rowtar,
(destid << 22) | (hopcount << 12) | ((offset & ~0x3) >> 9));
- data = (u8 *) maint_win + offset;
+ data = (u8 *) priv->maint_win + offset;
switch (len) {
case 1:
out_8((u8 *) data, val);
@@ -296,9 +320,10 @@ int
rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox,
void *buffer, size_t len)
{
+ struct rio_priv *priv = mport->priv;
u32 omr;
- struct rio_tx_desc *desc =
- (struct rio_tx_desc *)msg_tx_ring.virt + msg_tx_ring.tx_slot;
+ struct rio_tx_desc *desc = (struct rio_tx_desc *)priv->msg_tx_ring.virt
+ + priv->msg_tx_ring.tx_slot;
int ret = 0;
pr_debug
@@ -311,11 +336,11 @@ rio_hw_add_outb_message(struct rio_mport
}
/* Copy and clear rest of buffer */
- memcpy(msg_tx_ring.virt_buffer[msg_tx_ring.tx_slot], buffer, len);
+ memcpy(priv->msg_tx_ring.virt_buffer[priv->msg_tx_ring.tx_slot], buffer,
+ len);
if (len < (RIO_MAX_MSG_SIZE - 4))
- memset((void *)((u32) msg_tx_ring.
- virt_buffer[msg_tx_ring.tx_slot] + len), 0,
- RIO_MAX_MSG_SIZE - len);
+ memset(priv->msg_tx_ring.virt_buffer[priv->msg_tx_ring.tx_slot]
+ + len, 0, RIO_MAX_MSG_SIZE - len);
/* Set mbox field for message */
desc->dport = mbox & 0x3;
@@ -327,15 +352,16 @@ rio_hw_add_outb_message(struct rio_mport
desc->dwcnt = is_power_of_2(len) ? len : 1 << get_bitmask_order(len);
/* Set snooping and source buffer address */
- desc->saddr = 0x00000004 | msg_tx_ring.phys_buffer[msg_tx_ring.tx_slot];
+ desc->saddr = 0x00000004
+ | priv->msg_tx_ring.phys_buffer[priv->msg_tx_ring.tx_slot];
/* Increment enqueue pointer */
- omr = in_be32((void *)&msg_regs->omr);
- out_be32((void *)&msg_regs->omr, omr | RIO_MSG_OMR_MUI);
+ omr = in_be32(&priv->msg_regs->omr);
+ out_be32(&priv->msg_regs->omr, omr | RIO_MSG_OMR_MUI);
/* Go to next descriptor */
- if (++msg_tx_ring.tx_slot == msg_tx_ring.size)
- msg_tx_ring.tx_slot = 0;
+ if (++priv->msg_tx_ring.tx_slot == priv->msg_tx_ring.size)
+ priv->msg_tx_ring.tx_slot = 0;
out:
return ret;
@@ -356,28 +382,30 @@ fsl_rio_tx_handler(int irq, void *dev_in
{
int osr;
struct rio_mport *port = (struct rio_mport *)dev_instance;
+ struct rio_priv *priv = port->priv;
- osr = in_be32((void *)&msg_regs->osr);
+ osr = in_be32(&priv->msg_regs->osr);
if (osr & RIO_MSG_OSR_TE) {
pr_info("RIO: outbound message transmission error\n");
- out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_TE);
+ out_be32(&priv->msg_regs->osr, RIO_MSG_OSR_TE);
goto out;
}
if (osr & RIO_MSG_OSR_QOI) {
pr_info("RIO: outbound message queue overflow\n");
- out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_QOI);
+ out_be32(&priv->msg_regs->osr, RIO_MSG_OSR_QOI);
goto out;
}
if (osr & RIO_MSG_OSR_EOMI) {
- u32 dqp = in_be32((void *)&msg_regs->odqdpar);
- int slot = (dqp - msg_tx_ring.phys) >> 5;
- port->outb_msg[0].mcback(port, msg_tx_ring.dev_id, -1, slot);
+ u32 dqp = in_be32(&priv->msg_regs->odqdpar);
+ int slot = (dqp - priv->msg_tx_ring.phys) >> 5;
+ port->outb_msg[0].mcback(port, priv->msg_tx_ring.dev_id, -1,
+ slot);
/* Ack the end-of-message interrupt */
- out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_EOMI);
+ out_be32(&priv->msg_regs->osr, RIO_MSG_OSR_EOMI);
}
out:
@@ -398,6 +426,7 @@ fsl_rio_tx_handler(int irq, void *dev_in
int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
{
int i, j, rc = 0;
+ struct rio_priv *priv = mport->priv;
if ((entries < RIO_MIN_TX_RING_SIZE) ||
(entries > RIO_MAX_TX_RING_SIZE) || (!is_power_of_2(entries))) {
@@ -406,54 +435,53 @@ int rio_open_outb_mbox(struct rio_mport
}
/* Initialize shadow copy ring */
- msg_tx_ring.dev_id = dev_id;
- msg_tx_ring.size = entries;
+ priv->msg_tx_ring.dev_id = dev_id;
+ priv->msg_tx_ring.size = entries;
- for (i = 0; i < msg_tx_ring.size; i++) {
- if (!
- (msg_tx_ring.virt_buffer[i] =
- dma_alloc_coherent(NULL, RIO_MSG_BUFFER_SIZE,
- &msg_tx_ring.phys_buffer[i],
- GFP_KERNEL))) {
+ for (i = 0; i < priv->msg_tx_ring.size; i++) {
+ priv->msg_tx_ring.virt_buffer[i] =
+ dma_alloc_coherent(NULL, RIO_MSG_BUFFER_SIZE,
+ &priv->msg_tx_ring.phys_buffer[i], GFP_KERNEL);
+ if (!priv->msg_tx_ring.virt_buffer[i]) {
rc = -ENOMEM;
- for (j = 0; j < msg_tx_ring.size; j++)
- if (msg_tx_ring.virt_buffer[j])
+ for (j = 0; j < priv->msg_tx_ring.size; j++)
+ if (priv->msg_tx_ring.virt_buffer[j])
dma_free_coherent(NULL,
- RIO_MSG_BUFFER_SIZE,
- msg_tx_ring.
- virt_buffer[j],
- msg_tx_ring.
- phys_buffer[j]);
+ RIO_MSG_BUFFER_SIZE,
+ priv->msg_tx_ring.
+ virt_buffer[j],
+ priv->msg_tx_ring.
+ phys_buffer[j]);
goto out;
}
}
/* Initialize outbound message descriptor ring */
- if (!(msg_tx_ring.virt = dma_alloc_coherent(NULL,
- msg_tx_ring.size *
- RIO_MSG_DESC_SIZE,
- &msg_tx_ring.phys,
- GFP_KERNEL))) {
+ priv->msg_tx_ring.virt = dma_alloc_coherent(NULL,
+ priv->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
+ &priv->msg_tx_ring.phys, GFP_KERNEL);
+ if (!priv->msg_tx_ring.virt) {
rc = -ENOMEM;
goto out_dma;
}
- memset(msg_tx_ring.virt, 0, msg_tx_ring.size * RIO_MSG_DESC_SIZE);
- msg_tx_ring.tx_slot = 0;
+ memset(priv->msg_tx_ring.virt, 0,
+ priv->msg_tx_ring.size * RIO_MSG_DESC_SIZE);
+ priv->msg_tx_ring.tx_slot = 0;
/* Point dequeue/enqueue pointers at first entry in ring */
- out_be32((void *)&msg_regs->odqdpar, msg_tx_ring.phys);
- out_be32((void *)&msg_regs->odqepar, msg_tx_ring.phys);
+ out_be32(&priv->msg_regs->odqdpar, priv->msg_tx_ring.phys);
+ out_be32(&priv->msg_regs->odqepar, priv->msg_tx_ring.phys);
/* Configure for snooping */
- out_be32((void *)&msg_regs->osar, 0x00000004);
+ out_be32(&priv->msg_regs->osar, 0x00000004);
/* Clear interrupt status */
- out_be32((void *)&msg_regs->osr, 0x000000b3);
+ out_be32(&priv->msg_regs->osr, 0x000000b3);
/* Hook up outbound message handler */
- if ((rc =
- request_irq(MPC85xx_IRQ_RIO_TX, fsl_rio_tx_handler, 0,
- "msg_tx", (void *)mport)) < 0)
+ rc = request_irq(IRQ_RIO_TX(mport), fsl_rio_tx_handler, 0,
+ "msg_tx", (void *)mport);
+ if (rc < 0)
goto out_irq;
/*
@@ -463,28 +491,28 @@ int rio_open_outb_mbox(struct rio_mport
* Chaining mode
* Disable
*/
- out_be32((void *)&msg_regs->omr, 0x00100220);
+ out_be32(&priv->msg_regs->omr, 0x00100220);
/* Set number of entries */
- out_be32((void *)&msg_regs->omr,
- in_be32((void *)&msg_regs->omr) |
+ out_be32(&priv->msg_regs->omr,
+ in_be32(&priv->msg_regs->omr) |
((get_bitmask_order(entries) - 2) << 12));
/* Now enable the unit */
- out_be32((void *)&msg_regs->omr, in_be32((void *)&msg_regs->omr) | 0x1);
+ out_be32(&priv->msg_regs->omr, in_be32(&priv->msg_regs->omr) | 0x1);
out:
return rc;
out_irq:
- dma_free_coherent(NULL, msg_tx_ring.size * RIO_MSG_DESC_SIZE,
- msg_tx_ring.virt, msg_tx_ring.phys);
+ dma_free_coherent(NULL, priv->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
+ priv->msg_tx_ring.virt, priv->msg_tx_ring.phys);
out_dma:
- for (i = 0; i < msg_tx_ring.size; i++)
+ for (i = 0; i < priv->msg_tx_ring.size; i++)
dma_free_coherent(NULL, RIO_MSG_BUFFER_SIZE,
- msg_tx_ring.virt_buffer[i],
- msg_tx_ring.phys_buffer[i]);
+ priv->msg_tx_ring.virt_buffer[i],
+ priv->msg_tx_ring.phys_buffer[i]);
return rc;
}
@@ -499,15 +527,16 @@ int rio_open_outb_mbox(struct rio_mport
*/
void rio_close_outb_mbox(struct rio_mport *mport, int mbox)
{
+ struct rio_priv *priv = mport->priv;
/* Disable inbound message unit */
- out_be32((void *)&msg_regs->omr, 0);
+ out_be32(&priv->msg_regs->omr, 0);
/* Free ring */
- dma_free_coherent(NULL, msg_tx_ring.size * RIO_MSG_DESC_SIZE,
- msg_tx_ring.virt, msg_tx_ring.phys);
+ dma_free_coherent(NULL, priv->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
+ priv->msg_tx_ring.virt, priv->msg_tx_ring.phys);
/* Free interrupt */
- free_irq(MPC85xx_IRQ_RIO_TX, (void *)mport);
+ free_irq(IRQ_RIO_TX(mport), (void *)mport);
}
/**
@@ -523,12 +552,13 @@ fsl_rio_rx_handler(int irq, void *dev_in
{
int isr;
struct rio_mport *port = (struct rio_mport *)dev_instance;
+ struct rio_priv *priv = port->priv;
- isr = in_be32((void *)&msg_regs->isr);
+ isr = in_be32(&priv->msg_regs->isr);
if (isr & RIO_MSG_ISR_TE) {
pr_info("RIO: inbound message reception error\n");
- out_be32((void *)&msg_regs->isr, RIO_MSG_ISR_TE);
+ out_be32((void *)&priv->msg_regs->isr, RIO_MSG_ISR_TE);
goto out;
}
@@ -540,10 +570,10 @@ fsl_rio_rx_handler(int irq, void *dev_in
* make the callback with an unknown/invalid mailbox number
* argument.
*/
- port->inb_msg[0].mcback(port, msg_rx_ring.dev_id, -1, -1);
+ port->inb_msg[0].mcback(port, priv->msg_rx_ring.dev_id, -1, -1);
/* Ack the queueing interrupt */
- out_be32((void *)&msg_regs->isr, RIO_MSG_ISR_DIQI);
+ out_be32(&priv->msg_regs->isr, RIO_MSG_ISR_DIQI);
}
out:
@@ -564,6 +594,7 @@ fsl_rio_rx_handler(int irq, void *dev_in
int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
{
int i, rc = 0;
+ struct rio_priv *priv = mport->priv;
if ((entries < RIO_MIN_RX_RING_SIZE) ||
(entries > RIO_MAX_RX_RING_SIZE) || (!is_power_of_2(entries))) {
@@ -572,36 +603,35 @@ int rio_open_inb_mbox(struct rio_mport *
}
/* Initialize client buffer ring */
- msg_rx_ring.dev_id = dev_id;
- msg_rx_ring.size = entries;
- msg_rx_ring.rx_slot = 0;
- for (i = 0; i < msg_rx_ring.size; i++)
- msg_rx_ring.virt_buffer[i] = NULL;
+ priv->msg_rx_ring.dev_id = dev_id;
+ priv->msg_rx_ring.size = entries;
+ priv->msg_rx_ring.rx_slot = 0;
+ for (i = 0; i < priv->msg_rx_ring.size; i++)
+ priv->msg_rx_ring.virt_buffer[i] = NULL;
/* Initialize inbound message ring */
- if (!(msg_rx_ring.virt = dma_alloc_coherent(NULL,
- msg_rx_ring.size *
- RIO_MAX_MSG_SIZE,
- &msg_rx_ring.phys,
- GFP_KERNEL))) {
+ priv->msg_rx_ring.virt = dma_alloc_coherent(NULL,
+ priv->msg_rx_ring.size * RIO_MAX_MSG_SIZE,
+ &priv->msg_rx_ring.phys, GFP_KERNEL);
+ if (!priv->msg_rx_ring.virt) {
rc = -ENOMEM;
goto out;
}
/* Point dequeue/enqueue pointers at first entry in ring */
- out_be32((void *)&msg_regs->ifqdpar, (u32) msg_rx_ring.phys);
- out_be32((void *)&msg_regs->ifqepar, (u32) msg_rx_ring.phys);
+ out_be32(&priv->msg_regs->ifqdpar, (u32) priv->msg_rx_ring.phys);
+ out_be32(&priv->msg_regs->ifqepar, (u32) priv->msg_rx_ring.phys);
/* Clear interrupt status */
- out_be32((void *)&msg_regs->isr, 0x00000091);
+ out_be32(&priv->msg_regs->isr, 0x00000091);
/* Hook up inbound message handler */
- if ((rc =
- request_irq(MPC85xx_IRQ_RIO_RX, fsl_rio_rx_handler, 0,
- "msg_rx", (void *)mport)) < 0) {
+ rc = request_irq(IRQ_RIO_RX(mport), fsl_rio_rx_handler, 0,
+ "msg_rx", (void *)mport);
+ if (rc < 0) {
dma_free_coherent(NULL, RIO_MSG_BUFFER_SIZE,
- msg_tx_ring.virt_buffer[i],
- msg_tx_ring.phys_buffer[i]);
+ priv->msg_tx_ring.virt_buffer[i],
+ priv->msg_tx_ring.phys_buffer[i]);
goto out;
}
@@ -612,15 +642,13 @@ int rio_open_inb_mbox(struct rio_mport *
* Unmask all interrupt sources
* Disable
*/
- out_be32((void *)&msg_regs->imr, 0x001b0060);
+ out_be32(&priv->msg_regs->imr, 0x001b0060);
/* Set number of queue entries */
- out_be32((void *)&msg_regs->imr,
- in_be32((void *)&msg_regs->imr) |
- ((get_bitmask_order(entries) - 2) << 12));
+ setbits32(&priv->msg_regs->imr, (get_bitmask_order(entries) - 2) << 12);
/* Now enable the unit */
- out_be32((void *)&msg_regs->imr, in_be32((void *)&msg_regs->imr) | 0x1);
+ setbits32(&priv->msg_regs->imr, 0x1);
out:
return rc;
@@ -636,15 +664,16 @@ int rio_open_inb_mbox(struct rio_mport *
*/
void rio_close_inb_mbox(struct rio_mport *mport, int mbox)
{
+ struct rio_priv *priv = mport->priv;
/* Disable inbound message unit */
- out_be32((void *)&msg_regs->imr, 0);
+ out_be32(&priv->msg_regs->imr, 0);
/* Free ring */
- dma_free_coherent(NULL, msg_rx_ring.size * RIO_MAX_MSG_SIZE,
- msg_rx_ring.virt, msg_rx_ring.phys);
+ dma_free_coherent(NULL, priv->msg_rx_ring.size * RIO_MAX_MSG_SIZE,
+ priv->msg_rx_ring.virt, priv->msg_rx_ring.phys);
/* Free interrupt */
- free_irq(MPC85xx_IRQ_RIO_RX, (void *)mport);
+ free_irq(IRQ_RIO_RX(mport), (void *)mport);
}
/**
@@ -659,21 +688,22 @@ void rio_close_inb_mbox(struct rio_mport
int rio_hw_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf)
{
int rc = 0;
+ struct rio_priv *priv = mport->priv;
pr_debug("RIO: rio_hw_add_inb_buffer(), msg_rx_ring.rx_slot %d\n",
- msg_rx_ring.rx_slot);
+ priv->msg_rx_ring.rx_slot);
- if (msg_rx_ring.virt_buffer[msg_rx_ring.rx_slot]) {
+ if (priv->msg_rx_ring.virt_buffer[priv->msg_rx_ring.rx_slot]) {
printk(KERN_ERR
"RIO: error adding inbound buffer %d, buffer exists\n",
- msg_rx_ring.rx_slot);
+ priv->msg_rx_ring.rx_slot);
rc = -EINVAL;
goto out;
}
- msg_rx_ring.virt_buffer[msg_rx_ring.rx_slot] = buf;
- if (++msg_rx_ring.rx_slot == msg_rx_ring.size)
- msg_rx_ring.rx_slot = 0;
+ priv->msg_rx_ring.virt_buffer[priv->msg_rx_ring.rx_slot] = buf;
+ if (++priv->msg_rx_ring.rx_slot == priv->msg_rx_ring.size)
+ priv->msg_rx_ring.rx_slot = 0;
out:
return rc;
@@ -691,20 +721,21 @@ EXPORT_SYMBOL_GPL(rio_hw_add_inb_buffer)
*/
void *rio_hw_get_inb_message(struct rio_mport *mport, int mbox)
{
- u32 imr;
+ struct rio_priv *priv = mport->priv;
u32 phys_buf, virt_buf;
void *buf = NULL;
int buf_idx;
- phys_buf = in_be32((void *)&msg_regs->ifqdpar);
+ phys_buf = in_be32(&priv->msg_regs->ifqdpar);
/* If no more messages, then bail out */
- if (phys_buf == in_be32((void *)&msg_regs->ifqepar))
+ if (phys_buf == in_be32(&priv->msg_regs->ifqepar))
goto out2;
- virt_buf = (u32) msg_rx_ring.virt + (phys_buf - msg_rx_ring.phys);
- buf_idx = (phys_buf - msg_rx_ring.phys) / RIO_MAX_MSG_SIZE;
- buf = msg_rx_ring.virt_buffer[buf_idx];
+ virt_buf = (u32) priv->msg_rx_ring.virt + (phys_buf
+ - priv->msg_rx_ring.phys);
+ buf_idx = (phys_buf - priv->msg_rx_ring.phys) / RIO_MAX_MSG_SIZE;
+ buf = priv->msg_rx_ring.virt_buffer[buf_idx];
if (!buf) {
printk(KERN_ERR
@@ -716,11 +747,10 @@ void *rio_hw_get_inb_message(struct rio_
memcpy(buf, (void *)virt_buf, RIO_MAX_MSG_SIZE);
/* Clear the available buffer */
- msg_rx_ring.virt_buffer[buf_idx] = NULL;
+ priv->msg_rx_ring.virt_buffer[buf_idx] = NULL;
out1:
- imr = in_be32((void *)&msg_regs->imr);
- out_be32((void *)&msg_regs->imr, imr | RIO_MSG_IMR_MI);
+ setbits32(&priv->msg_regs->imr, RIO_MSG_IMR_MI);
out2:
return buf;
@@ -741,27 +771,27 @@ fsl_rio_dbell_handler(int irq, void *dev
{
int dsr;
struct rio_mport *port = (struct rio_mport *)dev_instance;
+ struct rio_priv *priv = port->priv;
- dsr = in_be32((void *)&msg_regs->dsr);
+ dsr = in_be32(&priv->msg_regs->dsr);
if (dsr & DOORBELL_DSR_TE) {
pr_info("RIO: doorbell reception error\n");
- out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_TE);
+ out_be32(&priv->msg_regs->dsr, DOORBELL_DSR_TE);
goto out;
}
if (dsr & DOORBELL_DSR_QFI) {
pr_info("RIO: doorbell queue full\n");
- out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_QFI);
+ out_be32(&priv->msg_regs->dsr, DOORBELL_DSR_QFI);
goto out;
}
/* XXX Need to check/dispatch until queue empty */
if (dsr & DOORBELL_DSR_DIQI) {
u32 dmsg =
- (u32) dbell_ring.virt +
- (in_be32((void *)&msg_regs->dqdpar) & 0xfff);
- u32 dmr;
+ (u32) priv->dbell_ring.virt +
+ (in_be32(&priv->msg_regs->dqdpar) & 0xfff);
struct rio_dbell *dbell;
int found = 0;
@@ -784,9 +814,8 @@ fsl_rio_dbell_handler(int irq, void *dev
("RIO: spurious doorbell, sid %2.2x tid %2.2x info %4.4x\n",
DBELL_SID(dmsg), DBELL_TID(dmsg), DBELL_INF(dmsg));
}
- dmr = in_be32((void *)&msg_regs->dmr);
- out_be32((void *)&msg_regs->dmr, dmr | DOORBELL_DMR_DI);
- out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_DIQI);
+ setbits32(&priv->msg_regs->dmr, DOORBELL_DMR_DI);
+ out_be32(&priv->msg_regs->dsr, DOORBELL_DSR_DIQI);
}
out:
@@ -803,12 +832,13 @@ fsl_rio_dbell_handler(int irq, void *dev
*/
static int fsl_rio_doorbell_init(struct rio_mport *mport)
{
+ struct rio_priv *priv = mport->priv;
int rc = 0;
/* Map outbound doorbell window immediately after maintenance window */
- if (!(dbell_win =
- (u32) ioremap(mport->iores.start + RIO_MAINT_WIN_SIZE,
- RIO_DBELL_WIN_SIZE))) {
+ priv->dbell_win = ioremap(mport->iores.start + RIO_MAINT_WIN_SIZE,
+ RIO_DBELL_WIN_SIZE);
+ if (!priv->dbell_win) {
printk(KERN_ERR
"RIO: unable to map outbound doorbell window\n");
rc = -ENOMEM;
@@ -816,37 +846,36 @@ static int fsl_rio_doorbell_init(struct
}
/* Initialize inbound doorbells */
- if (!(dbell_ring.virt = dma_alloc_coherent(NULL,
- 512 * DOORBELL_MESSAGE_SIZE,
- &dbell_ring.phys,
- GFP_KERNEL))) {
+ priv->dbell_ring.virt = dma_alloc_coherent(NULL, 512 *
+ DOORBELL_MESSAGE_SIZE, &priv->dbell_ring.phys, GFP_KERNEL);
+ if (!priv->dbell_ring.virt) {
printk(KERN_ERR "RIO: unable allocate inbound doorbell ring\n");
rc = -ENOMEM;
- iounmap((void *)dbell_win);
+ iounmap(priv->dbell_win);
goto out;
}
/* Point dequeue/enqueue pointers at first entry in ring */
- out_be32((void *)&msg_regs->dqdpar, (u32) dbell_ring.phys);
- out_be32((void *)&msg_regs->dqepar, (u32) dbell_ring.phys);
+ out_be32(&priv->msg_regs->dqdpar, (u32) priv->dbell_ring.phys);
+ out_be32(&priv->msg_regs->dqepar, (u32) priv->dbell_ring.phys);
/* Clear interrupt status */
- out_be32((void *)&msg_regs->dsr, 0x00000091);
+ out_be32(&priv->msg_regs->dsr, 0x00000091);
/* Hook up doorbell handler */
- if ((rc =
- request_irq(MPC85xx_IRQ_RIO_BELL, fsl_rio_dbell_handler, 0,
- "dbell_rx", (void *)mport) < 0)) {
- iounmap((void *)dbell_win);
+ rc = request_irq(IRQ_RIO_BELL(mport), fsl_rio_dbell_handler, 0,
+ "dbell_rx", (void *)mport);
+ if (rc < 0) {
+ iounmap(priv->dbell_win);
dma_free_coherent(NULL, 512 * DOORBELL_MESSAGE_SIZE,
- dbell_ring.virt, dbell_ring.phys);
+ priv->dbell_ring.virt, priv->dbell_ring.phys);
printk(KERN_ERR
"MPC85xx RIO: unable to request inbound doorbell irq");
goto out;
}
/* Configure doorbells for snooping, 512 entries, and enable */
- out_be32((void *)&msg_regs->dmr, 0x00108161);
+ out_be32(&priv->msg_regs->dmr, 0x00108161);
out:
return rc;
@@ -887,6 +916,8 @@ void fsl_rio_setup(int law_start, int la
{
struct rio_ops *ops;
struct rio_mport *port;
+ struct rio_priv *priv = NULL;
+ int rc;
ops = kmalloc(sizeof(struct rio_ops), GFP_KERNEL);
ops->lcread = fsl_local_config_read;
@@ -895,9 +926,17 @@ void fsl_rio_setup(int law_start, int la
ops->cwrite = fsl_rio_config_write;
ops->dsend = fsl_rio_doorbell_send;
- port = kmalloc(sizeof(struct rio_mport), GFP_KERNEL);
+ port = kzalloc(sizeof(struct rio_mport), GFP_KERNEL);
port->id = 0;
port->index = 0;
+
+ priv = kzalloc(sizeof(struct rio_priv), GFP_KERNEL);
+ if (!priv) {
+ printk(KERN_ERR "Can't alloc memory for 'priv'\n");
+ rc = -ENOMEM;
+ goto err;
+ }
+
INIT_LIST_HEAD(&port->dbells);
port->iores.start = law_start;
port->iores.end = law_start + law_size;
@@ -911,22 +950,32 @@ void fsl_rio_setup(int law_start, int la
port->ops = ops;
port->host_deviceid = fsl_rio_get_hdid(port->id);
+ port->priv = priv;
rio_register_mport(port);
- regs_win = (u32) ioremap(RIO_REGS_BASE, 0x20000);
- atmu_regs = (struct rio_atmu_regs *)(regs_win + RIO_ATMU_REGS_OFFSET);
- maint_atmu_regs = atmu_regs + 1;
- dbell_atmu_regs = atmu_regs + 2;
- msg_regs = (struct rio_msg_regs *)(regs_win + RIO_MSG_REGS_OFFSET);
+ priv->regs_win = ioremap(RIO_REGS_BASE, 0x20000);
+ priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win
+ + RIO_ATMU_REGS_OFFSET);
+ priv->maint_atmu_regs = priv->atmu_regs + 1;
+ priv->dbell_atmu_regs = priv->atmu_regs + 2;
+ priv->msg_regs = (struct rio_msg_regs *)(priv->regs_win
+ + RIO_MSG_REGS_OFFSET);
/* Configure maintenance transaction window */
- out_be32((void *)&maint_atmu_regs->rowbar, 0x000c0000);
- out_be32((void *)&maint_atmu_regs->rowar, 0x80077015);
+ out_be32(&priv->maint_atmu_regs->rowbar, 0x000c0000);
+ out_be32(&priv->maint_atmu_regs->rowar, 0x80077015);
- maint_win = (u32) ioremap(law_start, RIO_MAINT_WIN_SIZE);
+ priv->maint_win = ioremap(law_start, RIO_MAINT_WIN_SIZE);
/* Configure outbound doorbell window */
- out_be32((void *)&dbell_atmu_regs->rowbar, 0x000c0400);
- out_be32((void *)&dbell_atmu_regs->rowar, 0x8004200b);
+ out_be32(&priv->dbell_atmu_regs->rowbar, 0x000c0400);
+ out_be32(&priv->dbell_atmu_regs->rowar, 0x8004200b);
fsl_rio_doorbell_init(port);
+
+ return;
+err:
+ if (priv)
+ iounmap(priv->regs_win);
+ kfree(priv);
+ kfree(port);
}
diff -puN drivers/rapidio/rio-access.c~rapidio-add-rapidio-multi-mport-support drivers/rapidio/rio-access.c
--- a/drivers/rapidio/rio-access.c~rapidio-add-rapidio-multi-mport-support
+++ a/drivers/rapidio/rio-access.c
@@ -48,7 +48,7 @@ int __rio_local_read_config_##size \
u32 data = 0; \
if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
spin_lock_irqsave(&rio_config_lock, flags); \
- res = mport->ops->lcread(mport->id, offset, len, &data); \
+ res = mport->ops->lcread(mport, mport->id, offset, len, &data); \
*value = (type)data; \
spin_unlock_irqrestore(&rio_config_lock, flags); \
return res; \
@@ -71,7 +71,7 @@ int __rio_local_write_config_##size \
unsigned long flags; \
if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
spin_lock_irqsave(&rio_config_lock, flags); \
- res = mport->ops->lcwrite(mport->id, offset, len, value); \
+ res = mport->ops->lcwrite(mport, mport->id, offset, len, value);\
spin_unlock_irqrestore(&rio_config_lock, flags); \
return res; \
}
@@ -108,7 +108,7 @@ int rio_mport_read_config_##size \
u32 data = 0; \
if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
spin_lock_irqsave(&rio_config_lock, flags); \
- res = mport->ops->cread(mport->id, destid, hopcount, offset, len, &data); \
+ res = mport->ops->cread(mport, mport->id, destid, hopcount, offset, len, &data); \
*value = (type)data; \
spin_unlock_irqrestore(&rio_config_lock, flags); \
return res; \
@@ -131,7 +131,7 @@ int rio_mport_write_config_##size \
unsigned long flags; \
if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
spin_lock_irqsave(&rio_config_lock, flags); \
- res = mport->ops->cwrite(mport->id, destid, hopcount, offset, len, value); \
+ res = mport->ops->cwrite(mport, mport->id, destid, hopcount, offset, len, value); \
spin_unlock_irqrestore(&rio_config_lock, flags); \
return res; \
}
@@ -166,7 +166,7 @@ int rio_mport_send_doorbell(struct rio_m
unsigned long flags;
spin_lock_irqsave(&rio_doorbell_lock, flags);
- res = mport->ops->dsend(mport->id, destid, data);
+ res = mport->ops->dsend(mport, mport->id, destid, data);
spin_unlock_irqrestore(&rio_doorbell_lock, flags);
return res;
diff -puN include/linux/rio.h~rapidio-add-rapidio-multi-mport-support include/linux/rio.h
--- a/include/linux/rio.h~rapidio-add-rapidio-multi-mport-support
+++ a/include/linux/rio.h
@@ -163,6 +163,7 @@ struct rio_dbell {
* @id: Port ID, unique among all ports
* @index: Port index, unique among all port interfaces of the same type
* @name: Port name string
+ * @priv: Master port private data
*/
struct rio_mport {
struct list_head dbells; /* list of doorbell events */
@@ -178,6 +179,7 @@ struct rio_mport {
unsigned char index; /* port index, unique among all port
interfaces of the same type */
unsigned char name[40];
+ void *priv; /* Master port private data */
};
/**
@@ -229,13 +231,15 @@ struct rio_switch {
* @dsend: Callback to send a doorbell message.
*/
struct rio_ops {
- int (*lcread) (int index, u32 offset, int len, u32 * data);
- int (*lcwrite) (int index, u32 offset, int len, u32 data);
- int (*cread) (int index, u16 destid, u8 hopcount, u32 offset, int len,
- u32 * data);
- int (*cwrite) (int index, u16 destid, u8 hopcount, u32 offset, int len,
- u32 data);
- int (*dsend) (int index, u16 destid, u16 data);
+ int (*lcread) (struct rio_mport *mport, int index, u32 offset, int len,
+ u32 *data);
+ int (*lcwrite) (struct rio_mport *mport, int index, u32 offset, int len,
+ u32 data);
+ int (*cread) (struct rio_mport *mport, int index, u16 destid,
+ u8 hopcount, u32 offset, int len, u32 *data);
+ int (*cwrite) (struct rio_mport *mport, int index, u16 destid,
+ u8 hopcount, u32 offset, int len, u32 data);
+ int (*dsend) (struct rio_mport *mport, int index, u16 destid, u16 data);
};
#define RIO_RESOURCE_MEM 0x00000100
_
^ permalink raw reply
* [patch 24/24] rapidio: fix docbook references
From: akpm @ 2008-03-28 21:21 UTC (permalink / raw)
To: paulus; +Cc: randy.dunlap, linuxppc-dev, akpm
From: Randy Dunlap <randy.dunlap@oracle.com>
Fix rapidio docbook (file was removed) and fix header file kernel-doc.
Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
Acked-by: Zhang Wei <wei.zhang@freescale.com>
Cc: Matt Porter <mporter@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
Documentation/DocBook/rapidio.tmpl | 1 -
include/linux/rio.h | 4 ++--
2 files changed, 2 insertions(+), 3 deletions(-)
diff -puN Documentation/DocBook/rapidio.tmpl~rapidio-fix-docbook-references Documentation/DocBook/rapidio.tmpl
--- a/Documentation/DocBook/rapidio.tmpl~rapidio-fix-docbook-references
+++ a/Documentation/DocBook/rapidio.tmpl
@@ -133,7 +133,6 @@
!Idrivers/rapidio/rio-sysfs.c
</sect1>
<sect1 id="PPC32_support"><title>PPC32 support</title>
-!Iarch/powerpc/kernel/rio.c
!Earch/powerpc/sysdev/fsl_rio.c
!Iarch/powerpc/sysdev/fsl_rio.c
</sect1>
diff -puN include/linux/rio.h~rapidio-fix-docbook-references include/linux/rio.h
--- a/include/linux/rio.h~rapidio-fix-docbook-references
+++ a/include/linux/rio.h
@@ -327,7 +327,7 @@ struct rio_route_ops {
};
/**
- * Struct for RIO memory definition.
+ * struct rio_mem - struct for RIO memory definition.
* @node: Node in list of memories
* @virt: The virtual address for mapped memory accessing.
* @owner: The owner id of this memory.
@@ -346,7 +346,7 @@ struct rio_mem {
};
/**
- * Struct for RIO memory definition.
+ * struct rio_mem_ops - Struct for RIO memory operations 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.
_
^ permalink raw reply
* [patch 06/24] lmb: add lmb_alloc_nid()
From: akpm @ 2008-03-28 21:21 UTC (permalink / raw)
To: paulus; +Cc: davem, linuxppc-dev, tglx, akpm, mingo
From: David Miller <davem@davemloft.net>
A variant of lmb_alloc() that tries to allocate memory on a specified NUMA
node 'nid' but falls back to normal lmb_alloc() if that fails.
The caller provides a 'nid_range' function pointer which assists the
allocator. It is given args 'start', 'end', and pointer to integer
'this_nid'.
It places at 'this_nid' the NUMA node id that corresponds to 'start', and
returns the end address within 'start' to 'end' at which memory assosciated
with 'nid' ends.
This callback allows a platform to use lmb_alloc_nid() in just about any
context, even ones in which early_pfn_to_nid() might not be working yet.
This function will be used by the NUMA setup code on sparc64, and also it can
be used by powerpc, replacing it's hand crafted "careful_allocation()"
function in arch/powerpc/mm/numa.c
If x86 ever converts its NUMA support over to using the LMB helpers, it can
use this too as it has something entirely similar.
Signed-off-by: David S. Miller <davem@davemloft.net>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
include/linux/lmb.h | 2
lib/lmb.c | 86 +++++++++++++++++++++++++++++++++++++-----
2 files changed, 78 insertions(+), 10 deletions(-)
diff -puN include/linux/lmb.h~lmb-add-lmb_alloc_nid include/linux/lmb.h
--- a/include/linux/lmb.h~lmb-add-lmb_alloc_nid
+++ a/include/linux/lmb.h
@@ -42,6 +42,8 @@ extern void __init lmb_init(void);
extern void __init lmb_analyze(void);
extern long __init lmb_add(u64 base, u64 size);
extern long __init lmb_reserve(u64 base, u64 size);
+extern u64 __init lmb_alloc_nid(u64 size, u64 align, int nid,
+ u64 (*nid_range)(u64, u64, int *));
extern u64 __init lmb_alloc(u64 size, u64 align);
extern u64 __init lmb_alloc_base(u64 size,
u64, u64 max_addr);
diff -puN lib/lmb.c~lmb-add-lmb_alloc_nid lib/lmb.c
--- a/lib/lmb.c~lmb-add-lmb_alloc_nid
+++ a/lib/lmb.c
@@ -232,6 +232,82 @@ long __init lmb_overlaps_region(struct l
return (i < rgn->cnt) ? i : -1;
}
+static u64 lmb_align_down(u64 addr, u64 size)
+{
+ return addr & ~(size - 1);
+}
+
+static u64 lmb_align_up(u64 addr, u64 size)
+{
+ return (addr + (size - 1)) & ~(size - 1);
+}
+
+static u64 __init lmb_alloc_nid_unreserved(u64 start, u64 end,
+ u64 size, u64 align)
+{
+ u64 base;
+ long j;
+
+ base = lmb_align_down((end - size), align);
+ while (start <= base &&
+ ((j = lmb_overlaps_region(&lmb.reserved, base, size)) >= 0))
+ base = lmb_align_down(lmb.reserved.region[j].base - size,
+ align);
+
+ if (base != 0 && start <= base) {
+ if (lmb_add_region(&lmb.reserved, base,
+ lmb_align_up(size, align)) < 0)
+ base = ~(u64)0;
+ return base;
+ }
+
+ return ~(u64)0;
+}
+
+static u64 __init lmb_alloc_nid_region(struct lmb_property *mp,
+ u64 (*nid_range)(u64, u64, int *),
+ u64 size, u64 align, int nid)
+{
+ u64 start, end;
+
+ start = mp->base;
+ end = start + mp->size;
+
+ start = lmb_align_up(start, align);
+ while (start < end) {
+ u64 this_end;
+ int this_nid;
+
+ this_end = nid_range(start, end, &this_nid);
+ if (this_nid == nid) {
+ u64 ret = lmb_alloc_nid_unreserved(start, this_end,
+ size, align);
+ if (ret != ~(u64)0)
+ return ret;
+ }
+ start = this_end;
+ }
+
+ return ~(u64)0;
+}
+
+u64 __init lmb_alloc_nid(u64 size, u64 align, int nid,
+ u64 (*nid_range)(u64 start, u64 end, int *nid))
+{
+ struct lmb_region *mem = &lmb.memory;
+ int i;
+
+ for (i = 0; i < mem->cnt; i++) {
+ u64 ret = lmb_alloc_nid_region(&mem->region[i],
+ nid_range,
+ size, align, nid);
+ if (ret != ~(u64)0)
+ return ret;
+ }
+
+ return lmb_alloc(size, align);
+}
+
u64 __init lmb_alloc(u64 size, u64 align)
{
return lmb_alloc_base(size, align, LMB_ALLOC_ANYWHERE);
@@ -250,16 +326,6 @@ u64 __init lmb_alloc_base(u64 size, u64
return alloc;
}
-static u64 lmb_align_down(u64 addr, u64 size)
-{
- return addr & ~(size - 1);
-}
-
-static u64 lmb_align_up(u64 addr, u64 size)
-{
- return (addr + (size - 1)) & ~(size - 1);
-}
-
u64 __init __lmb_alloc_base(u64 size, u64 align, u64 max_addr)
{
long i, j;
_
^ permalink raw reply
* Re: [patch 6/6] PS3: Gelic network driver Wake-on-LAN support
From: Jeff Garzik @ 2008-03-28 21:59 UTC (permalink / raw)
To: Geoff Levand; +Cc: linuxppc-dev, paulus
In-Reply-To: <47EAECC3.1030200@am.sony.com>
Geoff Levand wrote:
> From: Masakazu Mokuno <mokuno@sm.sony.co.jp>
>
> Add Wake-on-LAN support to the PS3 Gelic network driver.
> Other OS WOL support was introduced in PS3 system firmware
> 2.20.
>
> Signed-off-by: Masakazu Mokuno <mokuno@sm.sony.co.jp>
> Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
> ---
> drivers/net/ps3_gelic_net.c | 81 ++++++++++++++++++++++++++++++++++++++++++++
> drivers/net/ps3_gelic_net.h | 20 ++++++++++
> 2 files changed, 101 insertions(+)
ACK
^ permalink raw reply
* Re: Please pull powerpc.git merge branch
From: Bartlomiej Sieka @ 2008-03-28 22:06 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, akpm, torvalds, linux-kernel
In-Reply-To: <18412.58902.189124.391104@cargo.ozlabs.ibm.com>
Paul Mackerras wrote:
> Linus,
>
> I have added another commit to the powerpc.git merge branch, so when
> you do:
>
> git pull \
> git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc.git merge
>
> you'll get a fix for a bug where the hardware data breakpoint would
> sometimes fail to trigger on powerpc, if multiple threads put a
> breakpoint on the same address. The bug has been around for a while
> and Michael Ellerman just found the cause and posted a fix.
Hello Paul,
What about http://patchwork.ozlabs.org/linuxppc/patch?id=17525 ? I don't
see it in the merge branch of your repository, and it would be nice to
get it upstream as it fixes boot problems on some MPC5200-based boards.
Regards,
Bartlomiej
^ permalink raw reply
* badness in gfar_timeout
From: Philippe De Muyter @ 2008-03-28 22:24 UTC (permalink / raw)
To: linuxppc-dev
Hi everybody,
When connected to a 10Mbit/Half hub, my mpc8540 board quickly falls in an
endless "NETDEV WATCHDOG: eth0: transmit timed out" loop. This has not
yet happened here when connected to a 100Mbit/Full switch. Problem
seems to be twofold, because the gfar_timeout does not fix the problem, but
causes another one with a 'badness' message. I am not familiar with
that, so does someone have a fix for either the timeout either the badness
problem. or at least an explanation for the 'badness' problem.
When that happens, network becomes and remains broken, but other processes
keep working.
Below is a short excerpt of the endless kernel log.
Philippe
------------[ cut here ]------------
Badness at c0041604 [verbose debug info unavailable]
NIP: c0041604 LR: c0193b5c CTR: c0194894
REGS: c035fd00 TRAP: 0700 Not tainted (2.6.25-rc6)
MSR: 00029000 <EE,ME> CR: 24002028 XER: 00000000
TASK = c0340490[0] 'swapper' THREAD: c035e000
GPR00: 00000001 c035fdb0 c0340490 00000029 cf86c000 00000001 000010e0 000000c3
GPR08: cf86c360 c035e000 d101a000 fffffffa 00001670 00000000 0fff1500 ffffffff
GPR16: 00800000 00000000 007fff00 007ffec0 00200200 c0373cc8 c0373ac8 c03738c8
GPR24: c03736c8 c035e000 c035fe28 c0340000 d101a000 00029000 00000029 cf86c360
NIP [c0041604] free_irq+0x28/0x124
LR [c0193b5c] stop_gfar+0xdc/0xe0
Call Trace:
[c035fdb0] [c0340000] 0xc0340000 (unreliable)
[c035fdd0] [c0193b5c] stop_gfar+0xdc/0xe0
[c035fdf0] [c01948ec] gfar_timeout+0x58/0x64
[c035fe00] [c0204c98] dev_watchdog+0x110/0x118
[c035fe20] [c0024b44] run_timer_softirq+0x15c/0x1c0
[c035fe70] [c0020390] __do_softirq+0x74/0xe0
[c035fe90] [c0004510] do_softirq+0x54/0x58
[c035fea0] [c0020240] irq_exit+0x48/0x58
[c035feb0] [c000b010] timer_interrupt+0xa8/0x10c
[c035fed0] [c000e37c] ret_from_except+0x0/0x18
[c035ff90] [c0007854] cpu_idle+0xbc/0xcc
[c035ffb0] [c0284050] 0xc0284050
[c035ffc0] [c03209c8] start_kernel+0x224/0x2a4
[c035fff0] [c00003a0] skpinv+0x2d0/0x30c
Instruction dump:
90030000 4e800020 9421ffe0 7c0802a6 bfa10014 54290024 90010024 7c7e1b78
8009000c 5400012e 7c0000d0 54000ffe <0f000000> 2b8301ff 419d0074 546b1838
NETDEV WATCHDOG: eth0: transmit timed out
------------[ cut here ]------------
Badness at c0041604 [verbose debug info unavailable]
NIP: c0041604 LR: c0193b5c CTR: c0194894
REGS: c035fd00 TRAP: 0700 Not tainted (2.6.25-rc6)
MSR: 00029000 <EE,ME> CR: 24002028 XER: 00000000
TASK = c0340490[0] 'swapper' THREAD: c035e000
GPR00: 00000001 c035fdb0 c0340490 00000029 cf86c000 00000001 000010e0 000000c3
GPR08: cf86c360 c035e000 d101a000 fffffffa 00001710 00000000 0fff1500 ffffffff
GPR16: 00800000 00000000 007fff00 007ffec0 00200200 c0373cc8 c0373ac8 c03738c8
GPR24: c03736c8 c035e000 c035fe28 c0340000 d101a000 00029000 00000029 cf86c360
NIP [c0041604] free_irq+0x28/0x124
LR [c0193b5c] stop_gfar+0xdc/0xe0
Call Trace:
[c035fdb0] [c0340000] 0xc0340000 (unreliable)
[c035fdd0] [c0193b5c] stop_gfar+0xdc/0xe0
[c035fdf0] [c01948ec] gfar_timeout+0x58/0x64
[c035fe00] [c0204c98] dev_watchdog+0x110/0x118
[c035fe20] [c0024b44] run_timer_softirq+0x15c/0x1c0
[c035fe70] [c0020390] __do_softirq+0x74/0xe0
[c035fe90] [c0004510] do_softirq+0x54/0x58
[c035fea0] [c0020240] irq_exit+0x48/0x58
[c035feb0] [c000b010] timer_interrupt+0xa8/0x10c
[c035fed0] [c000e37c] ret_from_except+0x0/0x18
[c035ff90] [c0007854] cpu_idle+0xbc/0xcc
[c035ffb0] [c0284050] 0xc0284050
[c035ffc0] [c03209c8] start_kernel+0x224/0x2a4
[c035fff0] [c00003a0] skpinv+0x2d0/0x30c
Instruction dump:
90030000 4e800020 9421ffe0 7c0802a6 bfa10014 54290024 90010024 7c7e1b78
8009000c 5400012e 7c0000d0 54000ffe <0f000000> 2b8301ff 419d0074 546b1838
INIT:NETDEV WATCHDOG: eth0: transmit timed out
------------[ cut here ]------------
^ permalink raw reply
* Re: Network Bad Kernel Access
From: Grant Likely @ 2008-03-28 23:24 UTC (permalink / raw)
To: Glenn.G.Hart, Stephen Neuendorffer, John Linn; +Cc: linuxppc-embedded
In-Reply-To: <OF268312ED.06BF1E68-ON85257344.0004544A-85257344.00059541@ct.wec.com>
On Sun, Aug 26, 2007 at 7:00 PM, <Glenn.G.Hart@us.westinghouse.com> wrote:
> I am having a problem with my network. I am using a V4FX12 running linux
> 2.6.21 with the TEMAC. I am running the PPC at 300 MHz and the TEMAC is
> configured for DMA and DRE on the Xmit and the Recv. I have tried varying
> the FIFO depth and enabling/disabling the checksum offloading. All produce
> the error below when under heavy network traffic (specifically sending data
> from the PPC). Has anybody seen this? It seems like I am overflowing some
> memory, but I am not sure what/where to increase it.
I'm seeing the same behavior on my platform except that I get it
almost immediately after bringing up the Ethernet interface. I've
only just started to debug this. The bug showed up when DMA+DRE+CSUM
were enabled on the core.
Stephen, John; does any of this look familiar?
Cheers,
g.
>
> Thanks,
> Glenn
>
>
>
> [ 484.696738] Oops: kernel access of bad area, sig: 11 [#1]
> [ 484.761286] NIP: c00e1ef4 LR: c00cfec0 CTR: c00cfe34
> [ 484.820650] REGS: c0483b10 TRAP: 0300 Not tainted (2.6.21)
> [ 484.889378] MSR: 00029030 <EE,ME,IR,DR> CR: 93005999 XER: e0000000
> [ 484.965410] DAR: bb857caf, DSISR: 00000000
> [ 485.014365] TASK = c0648b60[129] 'rcS' THREAD: c0482000
> [ 485.074765] GPR00: c04fdfb8 c0483bc0 c0648b60 bb857c2b c04fd9a0 c0483bcc
> 04000000 ff107ac0
> [ 485.174747] GPR08: 0000000f c04fdfb8 c04d2478 00010001 00648d10 1003c2e0
> 00000000 00000001
> [ 485.274732] GPR16: 00000003 c0483ed8 00004fd8 000005b4 000005b4 00000000
> 00000000 0001679c
> [ 485.374716] GPR24: 7ff8b398 3002afe0 0000000f c04d2000 c04d23b8 c06bbe60
> 00000003 c04d2320
> [ 485.476784] NIP [c00e1ef4] kfree_skb+0x8/0x3c
> [ 485.528858] LR [c00cfec0] SgSendHandlerBH+0x8c/0x1cc
> [ 485.588223] Call Trace:
> [ 485.617389] [c0483bc0] [c00cfec0] SgSendHandlerBH+0x8c/0x1cc
> (unreliable)
> [ 485.698628] [c0483bf0] [c0019218] tasklet_action+0x90/0xd4
> [ 485.764241] [c0483c00] [c0018ebc] __do_softirq+0x64/0xd0
> [ 485.827772] [c0483c20] [c00064a8] do_softirq+0x40/0x58
> [ 485.889221] [c0483c30] [c0018f74] irq_exit+0x38/0x48
> [ 485.948586] [c0483c40] [c0006450] do_IRQ+0x88/0xa0
> [ 486.005868] [c0483c50] [c00032d8] ret_from_except+0x0/0x18
> [ 486.071483] [c0483d10] [c0483d00] 0xc0483d00
> [ 486.122516] [c0483d20] [c00e17d4] __alloc_skb+0x48/0x11c
> [ 486.186048] [c0483d40] [c0109218] tcp_sendmsg+0x1ac/0xc40
> [ 486.250621] [c0483db0] [c0126b58] inet_sendmsg+0x60/0x74
> [ 486.314152] [c0483dd0] [c00dcf34] sock_aio_write+0xe0/0xfc
> [ 486.379765] [c0483e30] [c0050910] do_sync_write+0xb8/0x10c
> [ 486.445381] [c0483ef0] [c0050a40] vfs_write+0xdc/0x10c
> [ 486.506829] [c0483f10] [c0050b48] sys_write+0x4c/0x8c
> [ 486.567236] [c0483f40] [c0002c90] ret_from_syscall+0x0/0x3c
> [ 486.633888] Instruction dump:
> [ 486.669300] 0f000000 7fe3fb78 7d6803a6 4e800021 80010014 7fe3fb78
> 7c0803a6 bbc10008
> [ 486.761992] 38210010 4bfffe78 2c030000 4d820020 <80030084> 39230084
> 2f800001 409e0008
> [ 486.858162] Kernel panic - not syncing: Aiee, killing interrupt handler!
> [ 486.938382] Rebooting in 180 seconds..
>
>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* RE: Network Bad Kernel Access
From: John Linn @ 2008-03-28 23:29 UTC (permalink / raw)
To: Grant Likely, Glenn.G.Hart, Stephen Neuendorffer; +Cc: linuxppc-embedded
In-Reply-To: <fa686aa40803281624y7db3ca7cyc022bf78acf26f8@mail.gmail.com>
I'm not using DRE and CSUM yet. I have seen some weirdness similar to
that but hard to reproduce reliably to chase it.=20
I tend to see it with heavy traffic also, so maybe it's not related to
DRE & CSUM. I am running DMA.
-- John
-----Original Message-----
From: glikely@secretlab.ca [mailto:glikely@secretlab.ca] On Behalf Of
Grant Likely
Sent: Friday, March 28, 2008 5:25 PM
To: Glenn.G.Hart@us.westinghouse.com; Stephen Neuendorffer; John Linn
Cc: linuxppc-embedded@ozlabs.org
Subject: Re: Network Bad Kernel Access
On Sun, Aug 26, 2007 at 7:00 PM, <Glenn.G.Hart@us.westinghouse.com>
wrote:
> I am having a problem with my network. I am using a V4FX12 running
linux
> 2.6.21 with the TEMAC. I am running the PPC at 300 MHz and the TEMAC
is
> configured for DMA and DRE on the Xmit and the Recv. I have tried
varying
> the FIFO depth and enabling/disabling the checksum offloading. All
produce
> the error below when under heavy network traffic (specifically
sending data
> from the PPC). Has anybody seen this? It seems like I am
overflowing some
> memory, but I am not sure what/where to increase it.
I'm seeing the same behavior on my platform except that I get it
almost immediately after bringing up the Ethernet interface. I've
only just started to debug this. The bug showed up when DMA+DRE+CSUM
were enabled on the core.
Stephen, John; does any of this look familiar?
Cheers,
g.
>
> Thanks,
> Glenn
>
>
>
> [ 484.696738] Oops: kernel access of bad area, sig: 11 [#1]
> [ 484.761286] NIP: c00e1ef4 LR: c00cfec0 CTR: c00cfe34
> [ 484.820650] REGS: c0483b10 TRAP: 0300 Not tainted (2.6.21)
> [ 484.889378] MSR: 00029030 <EE,ME,IR,DR> CR: 93005999 XER:
e0000000
> [ 484.965410] DAR: bb857caf, DSISR: 00000000
> [ 485.014365] TASK =3D c0648b60[129] 'rcS' THREAD: c0482000
> [ 485.074765] GPR00: c04fdfb8 c0483bc0 c0648b60 bb857c2b c04fd9a0
c0483bcc
> 04000000 ff107ac0
> [ 485.174747] GPR08: 0000000f c04fdfb8 c04d2478 00010001 00648d10
1003c2e0
> 00000000 00000001
> [ 485.274732] GPR16: 00000003 c0483ed8 00004fd8 000005b4 000005b4
00000000
> 00000000 0001679c
> [ 485.374716] GPR24: 7ff8b398 3002afe0 0000000f c04d2000 c04d23b8
c06bbe60
> 00000003 c04d2320
> [ 485.476784] NIP [c00e1ef4] kfree_skb+0x8/0x3c
> [ 485.528858] LR [c00cfec0] SgSendHandlerBH+0x8c/0x1cc
> [ 485.588223] Call Trace:
> [ 485.617389] [c0483bc0] [c00cfec0] SgSendHandlerBH+0x8c/0x1cc
> (unreliable)
> [ 485.698628] [c0483bf0] [c0019218] tasklet_action+0x90/0xd4
> [ 485.764241] [c0483c00] [c0018ebc] __do_softirq+0x64/0xd0
> [ 485.827772] [c0483c20] [c00064a8] do_softirq+0x40/0x58
> [ 485.889221] [c0483c30] [c0018f74] irq_exit+0x38/0x48
> [ 485.948586] [c0483c40] [c0006450] do_IRQ+0x88/0xa0
> [ 486.005868] [c0483c50] [c00032d8] ret_from_except+0x0/0x18
> [ 486.071483] [c0483d10] [c0483d00] 0xc0483d00
> [ 486.122516] [c0483d20] [c00e17d4] __alloc_skb+0x48/0x11c
> [ 486.186048] [c0483d40] [c0109218] tcp_sendmsg+0x1ac/0xc40
> [ 486.250621] [c0483db0] [c0126b58] inet_sendmsg+0x60/0x74
> [ 486.314152] [c0483dd0] [c00dcf34] sock_aio_write+0xe0/0xfc
> [ 486.379765] [c0483e30] [c0050910] do_sync_write+0xb8/0x10c
> [ 486.445381] [c0483ef0] [c0050a40] vfs_write+0xdc/0x10c
> [ 486.506829] [c0483f10] [c0050b48] sys_write+0x4c/0x8c
> [ 486.567236] [c0483f40] [c0002c90] ret_from_syscall+0x0/0x3c
> [ 486.633888] Instruction dump:
> [ 486.669300] 0f000000 7fe3fb78 7d6803a6 4e800021 80010014 7fe3fb78
> 7c0803a6 bbc10008
> [ 486.761992] 38210010 4bfffe78 2c030000 4d820020 <80030084>
39230084
> 2f800001 409e0008
> [ 486.858162] Kernel panic - not syncing: Aiee, killing interrupt
handler!
> [ 486.938382] Rebooting in 180 seconds..
>
>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* [PATCH 0/9] powerpc: mv64x60 and prpmc2800 DTS cleanups
From: Dale Farnsworth @ 2008-03-28 23:39 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
This series of patches again attempts to clean up and document
the Marvell MV64x60 device tree. It supersedes Mark Greer's
series posted on 11 December 2007. See:
http://ozlabs.org/pipermail/linuxppc-dev/2007-December/047986.html
I think I've addressed all comments on that patch series, but I'm
open to further comments. :)
These apply on the powerpc-next branch, and I'd like to get them
into 2.6.26.
Thanks,
-Dale
^ permalink raw reply
* Re: [PATCH 1/9] [POWERPC] mv64x60: change FDT compatible prefix to mrvl
From: Dale Farnsworth @ 2008-03-28 23:42 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20080328233954.GA29499@farnsworth.org>
From: Dale Farnsworth <dale@farnsworth.org>
Follow the convention that compatible names are prefixed by the
vendor's stock ticker symbol. For Marvell Technology Group Ltd.,
that's MRVL.
Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
Acked-by: Mark A. Greer <mgreer@mvista.com>
Index: linux-2.6/arch/powerpc/boot/dts/prpmc2800.dts
===================================================================
--- linux-2.6.orig/arch/powerpc/boot/dts/prpmc2800.dts
+++ linux-2.6/arch/powerpc/boot/dts/prpmc2800.dts
@@ -44,7 +44,7 @@
#address-cells = <1>;
#size-cells = <1>;
model = "mv64360"; /* Default */
- compatible = "marvell,mv64x60";
+ compatible = "mrvl,mv64x60";
clock-frequency = <7f28155>; /* 133.333333 MHz */
reg = <f1000000 00010000>;
virtual-reg = <f1000000>;
@@ -72,7 +72,7 @@
#address-cells = <1>;
#size-cells = <0>;
device_type = "mdio";
- compatible = "marvell,mv64x60-mdio";
+ compatible = "mrvl,mv64x60-mdio";
ethernet-phy@1 {
device_type = "ethernet-phy";
compatible = "broadcom,bcm5421";
@@ -93,7 +93,7 @@
reg = <2000 2000>;
eth0 {
device_type = "network";
- compatible = "marvell,mv64x60-eth";
+ compatible = "mrvl,mv64x60-eth";
block-index = <0>;
interrupts = <20>;
interrupt-parent = <&/mv64x60/pic>;
@@ -102,7 +102,7 @@
};
eth1 {
device_type = "network";
- compatible = "marvell,mv64x60-eth";
+ compatible = "mrvl,mv64x60-eth";
block-index = <1>;
interrupts = <21>;
interrupt-parent = <&/mv64x60/pic>;
@@ -113,7 +113,7 @@
sdma@4000 {
device_type = "dma";
- compatible = "marvell,mv64x60-sdma";
+ compatible = "mrvl,mv64x60-sdma";
reg = <4000 c18>;
virtual-reg = <f1004000>;
interrupt-base = <0>;
@@ -123,7 +123,7 @@
sdma@6000 {
device_type = "dma";
- compatible = "marvell,mv64x60-sdma";
+ compatible = "mrvl,mv64x60-sdma";
reg = <6000 c18>;
virtual-reg = <f1006000>;
interrupt-base = <0>;
@@ -132,7 +132,7 @@
};
brg@b200 {
- compatible = "marvell,mv64x60-brg";
+ compatible = "mrvl,mv64x60-brg";
reg = <b200 8>;
clock-src = <8>;
clock-frequency = <7ed6b40>;
@@ -141,7 +141,7 @@
};
brg@b208 {
- compatible = "marvell,mv64x60-brg";
+ compatible = "mrvl,mv64x60-brg";
reg = <b208 8>;
clock-src = <8>;
clock-frequency = <7ed6b40>;
@@ -164,7 +164,7 @@
mpsc@8000 {
device_type = "serial";
- compatible = "marvell,mpsc";
+ compatible = "mrvl,mpsc";
reg = <8000 38>;
virtual-reg = <f1008000>;
sdma = <&/mv64x60/sdma@4000>;
@@ -184,7 +184,7 @@
mpsc@9000 {
device_type = "serial";
- compatible = "marvell,mpsc";
+ compatible = "mrvl,mpsc";
reg = <9000 38>;
virtual-reg = <f1009000>;
sdma = <&/mv64x60/sdma@6000>;
@@ -203,14 +203,14 @@
};
wdt@b410 { /* watchdog timer */
- compatible = "marvell,mv64x60-wdt";
+ compatible = "mrvl,mv64x60-wdt";
reg = <b410 8>;
timeout = <a>; /* wdt timeout in seconds */
};
i2c@c000 {
device_type = "i2c";
- compatible = "marvell,mv64x60-i2c";
+ compatible = "mrvl,mv64x60-i2c";
reg = <c000 20>;
virtual-reg = <f100c000>;
freq_m = <8>;
@@ -224,18 +224,18 @@
pic {
#interrupt-cells = <1>;
#address-cells = <0>;
- compatible = "marvell,mv64x60-pic";
+ compatible = "mrvl,mv64x60-pic";
reg = <0000 88>;
interrupt-controller;
};
mpp@f000 {
- compatible = "marvell,mv64x60-mpp";
+ compatible = "mrvl,mv64x60-mpp";
reg = <f000 10>;
};
gpp@f100 {
- compatible = "marvell,mv64x60-gpp";
+ compatible = "mrvl,mv64x60-gpp";
reg = <f100 20>;
};
@@ -244,7 +244,7 @@
#size-cells = <2>;
#interrupt-cells = <1>;
device_type = "pci";
- compatible = "marvell,mv64x60-pci";
+ compatible = "mrvl,mv64x60-pci";
reg = <0cf8 8>;
ranges = <01000000 0 0 88000000 0 01000000
02000000 0 80000000 80000000 0 08000000>;
@@ -281,28 +281,28 @@
};
cpu-error@0070 {
- compatible = "marvell,mv64x60-cpu-error";
+ compatible = "mrvl,mv64x60-cpu-error";
reg = <0070 10 0128 28>;
interrupts = <03>;
interrupt-parent = <&/mv64x60/pic>;
};
sram-ctrl@0380 {
- compatible = "marvell,mv64x60-sram-ctrl";
+ compatible = "mrvl,mv64x60-sram-ctrl";
reg = <0380 80>;
interrupts = <0d>;
interrupt-parent = <&/mv64x60/pic>;
};
pci-error@1d40 {
- compatible = "marvell,mv64x60-pci-error";
+ compatible = "mrvl,mv64x60-pci-error";
reg = <1d40 40 0c28 4>;
interrupts = <0c>;
interrupt-parent = <&/mv64x60/pic>;
};
mem-ctrl@1400 {
- compatible = "marvell,mv64x60-mem-ctrl";
+ compatible = "mrvl,mv64x60-mem-ctrl";
reg = <1400 60>;
interrupts = <11>;
interrupt-parent = <&/mv64x60/pic>;
Index: linux-2.6/arch/powerpc/boot/serial.c
===================================================================
--- linux-2.6.orig/arch/powerpc/boot/serial.c
+++ linux-2.6/arch/powerpc/boot/serial.c
@@ -119,7 +119,7 @@ int serial_console_init(void)
if (dt_is_compatible(devp, "ns16550"))
rc = ns16550_console_init(devp, &serial_cd);
- else if (dt_is_compatible(devp, "marvell,mpsc"))
+ else if (dt_is_compatible(devp, "mrvl,mpsc"))
rc = mpsc_console_init(devp, &serial_cd);
else if (dt_is_compatible(devp, "fsl,cpm1-scc-uart") ||
dt_is_compatible(devp, "fsl,cpm1-smc-uart") ||
Index: linux-2.6/arch/powerpc/platforms/embedded6xx/prpmc2800.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/embedded6xx/prpmc2800.c
+++ linux-2.6/arch/powerpc/platforms/embedded6xx/prpmc2800.c
@@ -49,13 +49,13 @@ static void __init prpmc2800_setup_arch(
* ioremap mpp and gpp registers in case they are later
* needed by prpmc2800_reset_board().
*/
- np = of_find_compatible_node(NULL, NULL, "marvell,mv64x60-mpp");
+ np = of_find_compatible_node(NULL, NULL, "mrvl,mv64x60-mpp");
reg = of_get_property(np, "reg", NULL);
paddr = of_translate_address(np, reg);
of_node_put(np);
mv64x60_mpp_reg_base = ioremap(paddr, reg[1]);
- np = of_find_compatible_node(NULL, NULL, "marvell,mv64x60-gpp");
+ np = of_find_compatible_node(NULL, NULL, "mrvl,mv64x60-gpp");
reg = of_get_property(np, "reg", NULL);
paddr = of_translate_address(np, reg);
of_node_put(np);
Index: linux-2.6/arch/powerpc/sysdev/mv64x60_dev.c
===================================================================
--- linux-2.6.orig/arch/powerpc/sysdev/mv64x60_dev.c
+++ linux-2.6/arch/powerpc/sysdev/mv64x60_dev.c
@@ -446,22 +446,22 @@ static int __init mv64x60_device_setup(v
int err;
id = 0;
- for_each_compatible_node(np, "serial", "marvell,mpsc")
+ for_each_compatible_node(np, "serial", "mrvl,mpsc")
if ((err = mv64x60_mpsc_device_setup(np, id++)))
goto error;
id = 0;
- for_each_compatible_node(np, "network", "marvell,mv64x60-eth")
+ for_each_compatible_node(np, "network", "mrvl,mv64x60-eth")
if ((err = mv64x60_eth_device_setup(np, id++)))
goto error;
id = 0;
- for_each_compatible_node(np, "i2c", "marvell,mv64x60-i2c")
+ for_each_compatible_node(np, "i2c", "mrvl,mv64x60-i2c")
if ((err = mv64x60_i2c_device_setup(np, id++)))
goto error;
/* support up to one watchdog timer */
- np = of_find_compatible_node(np, NULL, "marvell,mv64x60-wdt");
+ np = of_find_compatible_node(np, NULL, "mrvl,mv64x60-wdt");
if (np) {
if ((err = mv64x60_wdt_device_setup(np, id)))
goto error;
@@ -489,7 +489,7 @@ static int __init mv64x60_add_mpsc_conso
if (!np)
goto not_mpsc;
- if (!of_device_is_compatible(np, "marvell,mpsc"))
+ if (!of_device_is_compatible(np, "mrvl,mpsc"))
goto not_mpsc;
prop = of_get_property(np, "block-index", NULL);
Index: linux-2.6/arch/powerpc/sysdev/mv64x60_pci.c
===================================================================
--- linux-2.6.orig/arch/powerpc/sysdev/mv64x60_pci.c
+++ linux-2.6/arch/powerpc/sysdev/mv64x60_pci.c
@@ -86,14 +86,14 @@ static int __init mv64x60_sysfs_init(voi
struct platform_device *pdev;
const unsigned int *prop;
- np = of_find_compatible_node(NULL, NULL, "marvell,mv64x60");
+ np = of_find_compatible_node(NULL, NULL, "mrvl,mv64x60");
if (!np)
return 0;
prop = of_get_property(np, "hs_reg_valid", NULL);
of_node_put(np);
- pdev = platform_device_register_simple("marvell,mv64x60", 0, NULL, 0);
+ pdev = platform_device_register_simple("mrvl,mv64x60", 0, NULL, 0);
if (IS_ERR(pdev))
return PTR_ERR(pdev);
@@ -166,6 +166,6 @@ void __init mv64x60_pci_init(void)
{
struct device_node *np;
- for_each_compatible_node(np, "pci", "marvell,mv64x60-pci")
+ for_each_compatible_node(np, "pci", "mrvl,mv64x60-pci")
mv64x60_add_bridge(np);
}
Index: linux-2.6/arch/powerpc/sysdev/mv64x60_pic.c
===================================================================
--- linux-2.6.orig/arch/powerpc/sysdev/mv64x60_pic.c
+++ linux-2.6/arch/powerpc/sysdev/mv64x60_pic.c
@@ -238,13 +238,13 @@ void __init mv64x60_init_irq(void)
const unsigned int *reg;
unsigned long flags;
- np = of_find_compatible_node(NULL, NULL, "marvell,mv64x60-gpp");
+ np = of_find_compatible_node(NULL, NULL, "mrvl,mv64x60-gpp");
reg = of_get_property(np, "reg", &size);
paddr = of_translate_address(np, reg);
mv64x60_gpp_reg_base = ioremap(paddr, reg[1]);
of_node_put(np);
- np = of_find_compatible_node(NULL, NULL, "marvell,mv64x60-pic");
+ np = of_find_compatible_node(NULL, NULL, "mrvl,mv64x60-pic");
reg = of_get_property(np, "reg", &size);
paddr = of_translate_address(np, reg);
mv64x60_irq_reg_base = ioremap(paddr, reg[1]);
Index: linux-2.6/arch/powerpc/sysdev/mv64x60_udbg.c
===================================================================
--- linux-2.6.orig/arch/powerpc/sysdev/mv64x60_udbg.c
+++ linux-2.6/arch/powerpc/sysdev/mv64x60_udbg.c
@@ -85,7 +85,7 @@ static void mv64x60_udbg_init(void)
if (!stdout)
return;
- for_each_compatible_node(np, "serial", "marvell,mpsc") {
+ for_each_compatible_node(np, "serial", "mrvl,mpsc") {
if (np == stdout)
break;
}
^ permalink raw reply
* [PATCH 2/9] [POWERPC] prpmc2800: convert DTS to v1 and add labels
From: Dale Farnsworth @ 2008-03-28 23:44 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20080328233954.GA29499@farnsworth.org>
From: Mark A. Greer <mgreer@mvista.com>
Update the prpmc2800 DTS file to version 1 and add labels.
I verified that there was no change in the resulting dtb file.
Signed-off-by: Mark A. Greer <mgreer@mvista.com>
Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
Index: linux-2.6/arch/powerpc/boot/dts/prpmc2800.dts
===================================================================
--- linux-2.6.orig/arch/powerpc/boot/dts/prpmc2800.dts
+++ linux-2.6/arch/powerpc/boot/dts/prpmc2800.dts
@@ -11,6 +11,8 @@
* if it can determine the exact PrPMC type.
*/
+/dts-v1/;
+
/ {
#address-cells = <1>;
#size-cells = <1>;
@@ -25,19 +27,19 @@
PowerPC,7447 {
device_type = "cpu";
reg = <0>;
- clock-frequency = <2bb0b140>; /* Default (733 MHz) */
- bus-frequency = <7f28155>; /* 133.333333 MHz */
- timebase-frequency = <1fca055>; /* 33.333333 MHz */
- i-cache-line-size = <20>;
- d-cache-line-size = <20>;
- i-cache-size = <8000>;
- d-cache-size = <8000>;
+ clock-frequency = <733000000>; /* Default */
+ bus-frequency = <133333333>;
+ timebase-frequency = <33333333>;
+ i-cache-line-size = <32>;
+ d-cache-line-size = <32>;
+ i-cache-size = <32768>;
+ d-cache-size = <32768>;
};
};
memory {
device_type = "memory";
- reg = <00000000 20000000>; /* Default (512MB) */
+ reg = <0x0 0x20000000>; /* Default (512MB) */
};
mv64x60@f1000000 { /* Marvell Discovery */
@@ -45,26 +47,26 @@
#size-cells = <1>;
model = "mv64360"; /* Default */
compatible = "mrvl,mv64x60";
- clock-frequency = <7f28155>; /* 133.333333 MHz */
- reg = <f1000000 00010000>;
- virtual-reg = <f1000000>;
- ranges = <88000000 88000000 01000000 /* PCI 0 I/O Space */
- 80000000 80000000 08000000 /* PCI 0 MEM Space */
- a0000000 a0000000 04000000 /* User FLASH */
- 00000000 f1000000 00010000 /* Bridge's regs */
- f2000000 f2000000 00040000>; /* Integrated SRAM */
+ clock-frequency = <133333333>;
+ reg = <0xf1000000 0x10000>;
+ virtual-reg = <0xf1000000>;
+ ranges = <0x88000000 0x88000000 0x1000000 /* PCI 0 I/O Space */
+ 0x80000000 0x80000000 0x8000000 /* PCI 0 MEM Space */
+ 0xa0000000 0xa0000000 0x4000000 /* User FLASH */
+ 0x00000000 0xf1000000 0x0010000 /* Bridge's regs */
+ 0xf2000000 0xf2000000 0x0040000>;/* Integrated SRAM */
flash@a0000000 {
device_type = "rom";
compatible = "direct-mapped";
- reg = <a0000000 4000000>; /* Default (64MB) */
+ reg = <0xa0000000 0x4000000>; /* Default (64MB) */
probe-type = "CFI";
bank-width = <4>;
- partitions = <00000000 00100000 /* RO */
- 00100000 00040001 /* RW */
- 00140000 00400000 /* RO */
- 00540000 039c0000 /* RO */
- 03f00000 00100000>; /* RO */
+ partitions = <0x00000000 0x00100000 /* RO */
+ 0x00100000 0x00040001 /* RW */
+ 0x00140000 0x00400000 /* RO */
+ 0x00540000 0x039c0000 /* RO */
+ 0x03f00000 0x00100000>; /* RO */
partition-names = "FW Image A", "FW Config Data", "Kernel Image", "Filesystem", "FW Image B";
};
@@ -73,170 +75,170 @@
#size-cells = <0>;
device_type = "mdio";
compatible = "mrvl,mv64x60-mdio";
- ethernet-phy@1 {
+ PHY0: ethernet-phy@1 {
device_type = "ethernet-phy";
compatible = "broadcom,bcm5421";
- interrupts = <4c>; /* GPP 12 */
- interrupt-parent = <&/mv64x60/pic>;
+ interrupts = <76>; /* GPP 12 */
+ interrupt-parent = <&PIC>;
reg = <1>;
};
- ethernet-phy@3 {
+ PHY1: ethernet-phy@3 {
device_type = "ethernet-phy";
compatible = "broadcom,bcm5421";
- interrupts = <4c>; /* GPP 12 */
- interrupt-parent = <&/mv64x60/pic>;
+ interrupts = <76>; /* GPP 12 */
+ interrupt-parent = <&PIC>;
reg = <3>;
};
};
ethernet@2000 {
- reg = <2000 2000>;
+ reg = <0x2000 0x2000>;
eth0 {
device_type = "network";
compatible = "mrvl,mv64x60-eth";
block-index = <0>;
- interrupts = <20>;
- interrupt-parent = <&/mv64x60/pic>;
- phy = <&/mv64x60/mdio/ethernet-phy@1>;
+ interrupts = <32>;
+ interrupt-parent = <&PIC>;
+ phy = <&PHY0>;
local-mac-address = [ 00 00 00 00 00 00 ];
};
eth1 {
device_type = "network";
compatible = "mrvl,mv64x60-eth";
block-index = <1>;
- interrupts = <21>;
- interrupt-parent = <&/mv64x60/pic>;
- phy = <&/mv64x60/mdio/ethernet-phy@3>;
+ interrupts = <33>;
+ interrupt-parent = <&PIC>;
+ phy = <&PHY1>;
local-mac-address = [ 00 00 00 00 00 00 ];
};
};
- sdma@4000 {
+ SDMA0: sdma@4000 {
device_type = "dma";
compatible = "mrvl,mv64x60-sdma";
- reg = <4000 c18>;
- virtual-reg = <f1004000>;
+ reg = <0x4000 0xc18>;
+ virtual-reg = <0xf1004000>;
interrupt-base = <0>;
- interrupts = <24>;
- interrupt-parent = <&/mv64x60/pic>;
+ interrupts = <36>;
+ interrupt-parent = <&PIC>;
};
- sdma@6000 {
+ SDMA1: sdma@6000 {
device_type = "dma";
compatible = "mrvl,mv64x60-sdma";
- reg = <6000 c18>;
- virtual-reg = <f1006000>;
+ reg = <0x6000 0xc18>;
+ virtual-reg = <0xf1006000>;
interrupt-base = <0>;
- interrupts = <26>;
- interrupt-parent = <&/mv64x60/pic>;
+ interrupts = <38>;
+ interrupt-parent = <&PIC>;
};
- brg@b200 {
+ BRG0: brg@b200 {
compatible = "mrvl,mv64x60-brg";
- reg = <b200 8>;
+ reg = <0xb200 0x8>;
clock-src = <8>;
- clock-frequency = <7ed6b40>;
- current-speed = <2580>;
+ clock-frequency = <133000000>;
+ current-speed = <9600>;
bcr = <0>;
};
- brg@b208 {
+ BRG1: brg@b208 {
compatible = "mrvl,mv64x60-brg";
- reg = <b208 8>;
+ reg = <0xb208 0x8>;
clock-src = <8>;
- clock-frequency = <7ed6b40>;
- current-speed = <2580>;
+ clock-frequency = <133000000>;
+ current-speed = <9600>;
bcr = <0>;
};
- cunit@f200 {
- reg = <f200 200>;
+ CUNIT: cunit@f200 {
+ reg = <0xf200 0x200>;
};
- mpscrouting@b400 {
- reg = <b400 c>;
+ MPSCROUTING: mpscrouting@b400 {
+ reg = <0xb400 0xc>;
};
- mpscintr@b800 {
- reg = <b800 100>;
- virtual-reg = <f100b800>;
+ MPSCINTR: mpscintr@b800 {
+ reg = <0xb800 0x100>;
+ virtual-reg = <0xf100b800>;
};
- mpsc@8000 {
+ MPSC0: mpsc@8000 {
device_type = "serial";
compatible = "mrvl,mpsc";
- reg = <8000 38>;
- virtual-reg = <f1008000>;
- sdma = <&/mv64x60/sdma@4000>;
- brg = <&/mv64x60/brg@b200>;
- cunit = <&/mv64x60/cunit@f200>;
- mpscrouting = <&/mv64x60/mpscrouting@b400>;
- mpscintr = <&/mv64x60/mpscintr@b800>;
+ reg = <0x8000 0x38>;
+ virtual-reg = <0xf1008000>;
+ sdma = <&SDMA0>;
+ brg = <&BRG0>;
+ cunit = <&CUNIT>;
+ mpscrouting = <&MPSCROUTING>;
+ mpscintr = <&MPSCINTR>;
block-index = <0>;
- max_idle = <28>;
+ max_idle = <40>;
chr_1 = <0>;
chr_2 = <0>;
chr_10 = <3>;
mpcr = <0>;
- interrupts = <28>;
- interrupt-parent = <&/mv64x60/pic>;
+ interrupts = <40>;
+ interrupt-parent = <&PIC>;
};
- mpsc@9000 {
+ MPSC1: mpsc@9000 {
device_type = "serial";
compatible = "mrvl,mpsc";
- reg = <9000 38>;
- virtual-reg = <f1009000>;
- sdma = <&/mv64x60/sdma@6000>;
- brg = <&/mv64x60/brg@b208>;
- cunit = <&/mv64x60/cunit@f200>;
- mpscrouting = <&/mv64x60/mpscrouting@b400>;
- mpscintr = <&/mv64x60/mpscintr@b800>;
+ reg = <0x9000 0x38>;
+ virtual-reg = <0xf1009000>;
+ sdma = <&SDMA1>;
+ brg = <&BRG1>;
+ cunit = <&CUNIT>;
+ mpscrouting = <&MPSCROUTING>;
+ mpscintr = <&MPSCINTR>;
block-index = <1>;
- max_idle = <28>;
+ max_idle = <40>;
chr_1 = <0>;
chr_2 = <0>;
chr_10 = <3>;
mpcr = <0>;
- interrupts = <2a>;
- interrupt-parent = <&/mv64x60/pic>;
+ interrupts = <42>;
+ interrupt-parent = <&PIC>;
};
wdt@b410 { /* watchdog timer */
compatible = "mrvl,mv64x60-wdt";
- reg = <b410 8>;
- timeout = <a>; /* wdt timeout in seconds */
+ reg = <0xb410 0x8>;
+ timeout = <10>; /* wdt timeout in seconds */
};
i2c@c000 {
device_type = "i2c";
compatible = "mrvl,mv64x60-i2c";
- reg = <c000 20>;
- virtual-reg = <f100c000>;
+ reg = <0xc000 0x20>;
+ virtual-reg = <0xf100c000>;
freq_m = <8>;
freq_n = <3>;
- timeout = <3e8>; /* 1000 = 1 second */
+ timeout = <1000>; /* 1000 = 1 second */
retries = <1>;
- interrupts = <25>;
- interrupt-parent = <&/mv64x60/pic>;
+ interrupts = <37>;
+ interrupt-parent = <&PIC>;
};
- pic {
+ PIC: pic {
#interrupt-cells = <1>;
#address-cells = <0>;
compatible = "mrvl,mv64x60-pic";
- reg = <0000 88>;
+ reg = <0x0 0x88>;
interrupt-controller;
};
mpp@f000 {
compatible = "mrvl,mv64x60-mpp";
- reg = <f000 10>;
+ reg = <0xf000 0x10>;
};
gpp@f100 {
compatible = "mrvl,mv64x60-gpp";
- reg = <f100 20>;
+ reg = <0xf100 0x20>;
};
pci@80000000 {
@@ -245,72 +247,74 @@
#interrupt-cells = <1>;
device_type = "pci";
compatible = "mrvl,mv64x60-pci";
- reg = <0cf8 8>;
- ranges = <01000000 0 0 88000000 0 01000000
- 02000000 0 80000000 80000000 0 08000000>;
- bus-range = <0 ff>;
- clock-frequency = <3EF1480>;
- interrupt-pci-iack = <0c34>;
- interrupt-parent = <&/mv64x60/pic>;
- interrupt-map-mask = <f800 0 0 7>;
+ reg = <0xcf8 0x8>;
+ ranges = <0x01000000 0x0 0x0
+ 0x88000000 0x0 0x01000000
+ 0x02000000 0x0 0x80000000
+ 0x80000000 0x0 0x08000000>;
+ bus-range = <0 255>;
+ clock-frequency = <66000000>;
+ interrupt-pci-iack = <0xc34>;
+ interrupt-parent = <&PIC>;
+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
/* IDSEL 0x0a */
- 5000 0 0 1 &/mv64x60/pic 50
- 5000 0 0 2 &/mv64x60/pic 51
- 5000 0 0 3 &/mv64x60/pic 5b
- 5000 0 0 4 &/mv64x60/pic 5d
+ 0x5000 0 0 1 &PIC 80
+ 0x5000 0 0 2 &PIC 81
+ 0x5000 0 0 3 &PIC 91
+ 0x5000 0 0 4 &PIC 93
/* IDSEL 0x0b */
- 5800 0 0 1 &/mv64x60/pic 5b
- 5800 0 0 2 &/mv64x60/pic 5d
- 5800 0 0 3 &/mv64x60/pic 50
- 5800 0 0 4 &/mv64x60/pic 51
+ 0x5800 0 0 1 &PIC 91
+ 0x5800 0 0 2 &PIC 93
+ 0x5800 0 0 3 &PIC 80
+ 0x5800 0 0 4 &PIC 81
/* IDSEL 0x0c */
- 6000 0 0 1 &/mv64x60/pic 5b
- 6000 0 0 2 &/mv64x60/pic 5d
- 6000 0 0 3 &/mv64x60/pic 50
- 6000 0 0 4 &/mv64x60/pic 51
+ 0x6000 0 0 1 &PIC 91
+ 0x6000 0 0 2 &PIC 93
+ 0x6000 0 0 3 &PIC 80
+ 0x6000 0 0 4 &PIC 81
/* IDSEL 0x0d */
- 6800 0 0 1 &/mv64x60/pic 5d
- 6800 0 0 2 &/mv64x60/pic 50
- 6800 0 0 3 &/mv64x60/pic 51
- 6800 0 0 4 &/mv64x60/pic 5b
+ 0x6800 0 0 1 &PIC 93
+ 0x6800 0 0 2 &PIC 80
+ 0x6800 0 0 3 &PIC 81
+ 0x6800 0 0 4 &PIC 91
>;
};
cpu-error@0070 {
compatible = "mrvl,mv64x60-cpu-error";
- reg = <0070 10 0128 28>;
- interrupts = <03>;
- interrupt-parent = <&/mv64x60/pic>;
+ reg = <0x70 0x10 0x128 0x28>;
+ interrupts = <3>;
+ interrupt-parent = <&PIC>;
};
sram-ctrl@0380 {
compatible = "mrvl,mv64x60-sram-ctrl";
- reg = <0380 80>;
- interrupts = <0d>;
- interrupt-parent = <&/mv64x60/pic>;
+ reg = <0x380 0x80>;
+ interrupts = <13>;
+ interrupt-parent = <&PIC>;
};
pci-error@1d40 {
compatible = "mrvl,mv64x60-pci-error";
- reg = <1d40 40 0c28 4>;
- interrupts = <0c>;
- interrupt-parent = <&/mv64x60/pic>;
+ reg = <0x1d40 0x40 0xc28 0x4>;
+ interrupts = <12>;
+ interrupt-parent = <&PIC>;
};
mem-ctrl@1400 {
compatible = "mrvl,mv64x60-mem-ctrl";
- reg = <1400 60>;
- interrupts = <11>;
- interrupt-parent = <&/mv64x60/pic>;
+ reg = <0x1400 0x60>;
+ interrupts = <17>;
+ interrupt-parent = <&PIC>;
};
};
chosen {
bootargs = "ip=on";
- linux,stdout-path = "/mv64x60@f1000000/mpsc@8000";
+ linux,stdout-path = &MPSC0;
};
};
^ permalink raw reply
* [PATCH 3/9] [POWERPC] prpmc2800: fix frequencies in prpmc2800.dts
From: Dale Farnsworth @ 2008-03-28 23:45 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20080328233954.GA29499@farnsworth.org>
From: Dale Farnsworth <dale@farnsworth.org>
After the conversion to dts v1 format, seeing the frequencies
in decimal made it obvious that some of them had been
incorrectly truncated. This fixes them. Note that the PCI
frequency comes from a different source and is documented
as 66MHz, so it was left at 66000000.
Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
Acked-by: Mark A. Greer <mgreer@mvista.com>
Index: linux-2.6/arch/powerpc/boot/dts/prpmc2800.dts
===================================================================
--- linux-2.6.orig/arch/powerpc/boot/dts/prpmc2800.dts
+++ linux-2.6/arch/powerpc/boot/dts/prpmc2800.dts
@@ -27,7 +27,7 @@
PowerPC,7447 {
device_type = "cpu";
reg = <0>;
- clock-frequency = <733000000>; /* Default */
+ clock-frequency = <733333333>; /* Default */
bus-frequency = <133333333>;
timebase-frequency = <33333333>;
i-cache-line-size = <32>;
@@ -137,7 +137,7 @@
compatible = "mrvl,mv64x60-brg";
reg = <0xb200 0x8>;
clock-src = <8>;
- clock-frequency = <133000000>;
+ clock-frequency = <133333333>;
current-speed = <9600>;
bcr = <0>;
};
@@ -146,7 +146,7 @@
compatible = "mrvl,mv64x60-brg";
reg = <0xb208 0x8>;
clock-src = <8>;
- clock-frequency = <133000000>;
+ clock-frequency = <133333333>;
current-speed = <9600>;
bcr = <0>;
};
^ permalink raw reply
* [PATCH 4/9] [POWERPC] mv64x60: Fix FDT compatible names: mv64x60 => mv64360
From: Dale Farnsworth @ 2008-03-28 23:47 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20080328233954.GA29499@farnsworth.org>
From: Mark A. Greer <mgreer@mvista.com>
Compatible names should refer to a specific version of the hardware,
without wildcards. Change each instance of mv64x60 to mv64360, which
is the oldest version we currently support.
Signed-off-by: Mark A. Greer <mgreer@mvista.com>
Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
Index: linux-2.6/arch/powerpc/boot/dts/prpmc2800.dts
===================================================================
--- linux-2.6.orig/arch/powerpc/boot/dts/prpmc2800.dts
+++ linux-2.6/arch/powerpc/boot/dts/prpmc2800.dts
@@ -46,7 +46,7 @@
#address-cells = <1>;
#size-cells = <1>;
model = "mv64360"; /* Default */
- compatible = "mrvl,mv64x60";
+ compatible = "mrvl,mv64360";
clock-frequency = <133333333>;
reg = <0xf1000000 0x10000>;
virtual-reg = <0xf1000000>;
@@ -74,7 +74,7 @@
#address-cells = <1>;
#size-cells = <0>;
device_type = "mdio";
- compatible = "mrvl,mv64x60-mdio";
+ compatible = "mrvl,mv64360-mdio";
PHY0: ethernet-phy@1 {
device_type = "ethernet-phy";
compatible = "broadcom,bcm5421";
@@ -95,7 +95,7 @@
reg = <0x2000 0x2000>;
eth0 {
device_type = "network";
- compatible = "mrvl,mv64x60-eth";
+ compatible = "mrvl,mv64360-eth";
block-index = <0>;
interrupts = <32>;
interrupt-parent = <&PIC>;
@@ -104,7 +104,7 @@
};
eth1 {
device_type = "network";
- compatible = "mrvl,mv64x60-eth";
+ compatible = "mrvl,mv64360-eth";
block-index = <1>;
interrupts = <33>;
interrupt-parent = <&PIC>;
@@ -115,7 +115,7 @@
SDMA0: sdma@4000 {
device_type = "dma";
- compatible = "mrvl,mv64x60-sdma";
+ compatible = "mrvl,mv64360-sdma";
reg = <0x4000 0xc18>;
virtual-reg = <0xf1004000>;
interrupt-base = <0>;
@@ -125,7 +125,7 @@
SDMA1: sdma@6000 {
device_type = "dma";
- compatible = "mrvl,mv64x60-sdma";
+ compatible = "mrvl,mv64360-sdma";
reg = <0x6000 0xc18>;
virtual-reg = <0xf1006000>;
interrupt-base = <0>;
@@ -134,7 +134,7 @@
};
BRG0: brg@b200 {
- compatible = "mrvl,mv64x60-brg";
+ compatible = "mrvl,mv64360-brg";
reg = <0xb200 0x8>;
clock-src = <8>;
clock-frequency = <133333333>;
@@ -143,7 +143,7 @@
};
BRG1: brg@b208 {
- compatible = "mrvl,mv64x60-brg";
+ compatible = "mrvl,mv64360-brg";
reg = <0xb208 0x8>;
clock-src = <8>;
clock-frequency = <133333333>;
@@ -166,7 +166,7 @@
MPSC0: mpsc@8000 {
device_type = "serial";
- compatible = "mrvl,mpsc";
+ compatible = "mrvl,mv64360-mpsc";
reg = <0x8000 0x38>;
virtual-reg = <0xf1008000>;
sdma = <&SDMA0>;
@@ -186,7 +186,7 @@
MPSC1: mpsc@9000 {
device_type = "serial";
- compatible = "mrvl,mpsc";
+ compatible = "mrvl,mv64360-mpsc";
reg = <0x9000 0x38>;
virtual-reg = <0xf1009000>;
sdma = <&SDMA1>;
@@ -205,14 +205,14 @@
};
wdt@b410 { /* watchdog timer */
- compatible = "mrvl,mv64x60-wdt";
+ compatible = "mrvl,mv64360-wdt";
reg = <0xb410 0x8>;
timeout = <10>; /* wdt timeout in seconds */
};
i2c@c000 {
device_type = "i2c";
- compatible = "mrvl,mv64x60-i2c";
+ compatible = "mrvl,mv64360-i2c";
reg = <0xc000 0x20>;
virtual-reg = <0xf100c000>;
freq_m = <8>;
@@ -226,18 +226,18 @@
PIC: pic {
#interrupt-cells = <1>;
#address-cells = <0>;
- compatible = "mrvl,mv64x60-pic";
+ compatible = "mrvl,mv64360-pic";
reg = <0x0 0x88>;
interrupt-controller;
};
mpp@f000 {
- compatible = "mrvl,mv64x60-mpp";
+ compatible = "mrvl,mv64360-mpp";
reg = <0xf000 0x10>;
};
gpp@f100 {
- compatible = "mrvl,mv64x60-gpp";
+ compatible = "mrvl,mv64360-gpp";
reg = <0xf100 0x20>;
};
@@ -246,7 +246,7 @@
#size-cells = <2>;
#interrupt-cells = <1>;
device_type = "pci";
- compatible = "mrvl,mv64x60-pci";
+ compatible = "mrvl,mv64360-pci";
reg = <0xcf8 0x8>;
ranges = <0x01000000 0x0 0x0
0x88000000 0x0 0x01000000
@@ -285,28 +285,28 @@
};
cpu-error@0070 {
- compatible = "mrvl,mv64x60-cpu-error";
+ compatible = "mrvl,mv64360-cpu-error";
reg = <0x70 0x10 0x128 0x28>;
interrupts = <3>;
interrupt-parent = <&PIC>;
};
sram-ctrl@0380 {
- compatible = "mrvl,mv64x60-sram-ctrl";
+ compatible = "mrvl,mv64360-sram-ctrl";
reg = <0x380 0x80>;
interrupts = <13>;
interrupt-parent = <&PIC>;
};
pci-error@1d40 {
- compatible = "mrvl,mv64x60-pci-error";
+ compatible = "mrvl,mv64360-pci-error";
reg = <0x1d40 0x40 0xc28 0x4>;
interrupts = <12>;
interrupt-parent = <&PIC>;
};
mem-ctrl@1400 {
- compatible = "mrvl,mv64x60-mem-ctrl";
+ compatible = "mrvl,mv64360-mem-ctrl";
reg = <0x1400 0x60>;
interrupts = <17>;
interrupt-parent = <&PIC>;
Index: linux-2.6/arch/powerpc/boot/serial.c
===================================================================
--- linux-2.6.orig/arch/powerpc/boot/serial.c
+++ linux-2.6/arch/powerpc/boot/serial.c
@@ -119,7 +119,7 @@ int serial_console_init(void)
if (dt_is_compatible(devp, "ns16550"))
rc = ns16550_console_init(devp, &serial_cd);
- else if (dt_is_compatible(devp, "mrvl,mpsc"))
+ else if (dt_is_compatible(devp, "mrvl,mv64360-mpsc"))
rc = mpsc_console_init(devp, &serial_cd);
else if (dt_is_compatible(devp, "fsl,cpm1-scc-uart") ||
dt_is_compatible(devp, "fsl,cpm1-smc-uart") ||
Index: linux-2.6/arch/powerpc/platforms/embedded6xx/prpmc2800.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/embedded6xx/prpmc2800.c
+++ linux-2.6/arch/powerpc/platforms/embedded6xx/prpmc2800.c
@@ -49,13 +49,13 @@ static void __init prpmc2800_setup_arch(
* ioremap mpp and gpp registers in case they are later
* needed by prpmc2800_reset_board().
*/
- np = of_find_compatible_node(NULL, NULL, "mrvl,mv64x60-mpp");
+ np = of_find_compatible_node(NULL, NULL, "mrvl,mv64360-mpp");
reg = of_get_property(np, "reg", NULL);
paddr = of_translate_address(np, reg);
of_node_put(np);
mv64x60_mpp_reg_base = ioremap(paddr, reg[1]);
- np = of_find_compatible_node(NULL, NULL, "mrvl,mv64x60-gpp");
+ np = of_find_compatible_node(NULL, NULL, "mrvl,mv64360-gpp");
reg = of_get_property(np, "reg", NULL);
paddr = of_translate_address(np, reg);
of_node_put(np);
Index: linux-2.6/arch/powerpc/sysdev/mv64x60_dev.c
===================================================================
--- linux-2.6.orig/arch/powerpc/sysdev/mv64x60_dev.c
+++ linux-2.6/arch/powerpc/sysdev/mv64x60_dev.c
@@ -446,22 +446,22 @@ static int __init mv64x60_device_setup(v
int err;
id = 0;
- for_each_compatible_node(np, "serial", "mrvl,mpsc")
+ for_each_compatible_node(np, "serial", "mrvl,mv64360-mpsc")
if ((err = mv64x60_mpsc_device_setup(np, id++)))
goto error;
id = 0;
- for_each_compatible_node(np, "network", "mrvl,mv64x60-eth")
+ for_each_compatible_node(np, "network", "mrvl,mv64360-eth")
if ((err = mv64x60_eth_device_setup(np, id++)))
goto error;
id = 0;
- for_each_compatible_node(np, "i2c", "mrvl,mv64x60-i2c")
+ for_each_compatible_node(np, "i2c", "mrvl,mv64360-i2c")
if ((err = mv64x60_i2c_device_setup(np, id++)))
goto error;
/* support up to one watchdog timer */
- np = of_find_compatible_node(np, NULL, "mrvl,mv64x60-wdt");
+ np = of_find_compatible_node(np, NULL, "mrvl,mv64360-wdt");
if (np) {
if ((err = mv64x60_wdt_device_setup(np, id)))
goto error;
@@ -489,7 +489,7 @@ static int __init mv64x60_add_mpsc_conso
if (!np)
goto not_mpsc;
- if (!of_device_is_compatible(np, "mrvl,mpsc"))
+ if (!of_device_is_compatible(np, "mrvl,mv64360-mpsc"))
goto not_mpsc;
prop = of_get_property(np, "block-index", NULL);
Index: linux-2.6/arch/powerpc/sysdev/mv64x60_pci.c
===================================================================
--- linux-2.6.orig/arch/powerpc/sysdev/mv64x60_pci.c
+++ linux-2.6/arch/powerpc/sysdev/mv64x60_pci.c
@@ -86,14 +86,14 @@ static int __init mv64x60_sysfs_init(voi
struct platform_device *pdev;
const unsigned int *prop;
- np = of_find_compatible_node(NULL, NULL, "mrvl,mv64x60");
+ np = of_find_compatible_node(NULL, NULL, "mrvl,mv64360");
if (!np)
return 0;
prop = of_get_property(np, "hs_reg_valid", NULL);
of_node_put(np);
- pdev = platform_device_register_simple("mrvl,mv64x60", 0, NULL, 0);
+ pdev = platform_device_register_simple("mrvl,mv64360", 0, NULL, 0);
if (IS_ERR(pdev))
return PTR_ERR(pdev);
@@ -166,6 +166,6 @@ void __init mv64x60_pci_init(void)
{
struct device_node *np;
- for_each_compatible_node(np, "pci", "mrvl,mv64x60-pci")
+ for_each_compatible_node(np, "pci", "mrvl,mv64360-pci")
mv64x60_add_bridge(np);
}
Index: linux-2.6/arch/powerpc/sysdev/mv64x60_pic.c
===================================================================
--- linux-2.6.orig/arch/powerpc/sysdev/mv64x60_pic.c
+++ linux-2.6/arch/powerpc/sysdev/mv64x60_pic.c
@@ -238,13 +238,13 @@ void __init mv64x60_init_irq(void)
const unsigned int *reg;
unsigned long flags;
- np = of_find_compatible_node(NULL, NULL, "mrvl,mv64x60-gpp");
+ np = of_find_compatible_node(NULL, NULL, "mrvl,mv64360-gpp");
reg = of_get_property(np, "reg", &size);
paddr = of_translate_address(np, reg);
mv64x60_gpp_reg_base = ioremap(paddr, reg[1]);
of_node_put(np);
- np = of_find_compatible_node(NULL, NULL, "mrvl,mv64x60-pic");
+ np = of_find_compatible_node(NULL, NULL, "mrvl,mv64360-pic");
reg = of_get_property(np, "reg", &size);
paddr = of_translate_address(np, reg);
mv64x60_irq_reg_base = ioremap(paddr, reg[1]);
Index: linux-2.6/arch/powerpc/sysdev/mv64x60_udbg.c
===================================================================
--- linux-2.6.orig/arch/powerpc/sysdev/mv64x60_udbg.c
+++ linux-2.6/arch/powerpc/sysdev/mv64x60_udbg.c
@@ -85,7 +85,7 @@ static void mv64x60_udbg_init(void)
if (!stdout)
return;
- for_each_compatible_node(np, "serial", "mrvl,mpsc") {
+ for_each_compatible_node(np, "serial", "mrvl,mv64360-mpsc") {
if (np == stdout)
break;
}
^ permalink raw reply
* Re: [PATCH 1/9] [POWERPC] mv64x60: change FDT compatible prefix to mrvl
From: Grant Likely @ 2008-03-28 23:47 UTC (permalink / raw)
To: Dale Farnsworth; +Cc: linuxppc-dev, paulus
In-Reply-To: <20080328234241.GA30214@farnsworth.org>
On Fri, Mar 28, 2008 at 5:42 PM, Dale Farnsworth <dale@farnsworth.org> wrote:
> From: Dale Farnsworth <dale@farnsworth.org>
>
> Follow the convention that compatible names are prefixed by the
> vendor's stock ticker symbol. For Marvell Technology Group Ltd.,
> that's MRVL.
>
> Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
> Acked-by: Mark A. Greer <mgreer@mvista.com>
Are there any boards "in the wild" using the old string? If so are
does changing this string risk complicating upgrades to a new kernel
version?
g.
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* [PATCH 5/9] [POWERPC] mv64x60: remove device tree absolute path references
From: Dale Farnsworth @ 2008-03-28 23:48 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20080328233954.GA29499@farnsworth.org>
From: Dale Farnsworth <dale@farnsworth.org>
Replace several device node absolute path lookups in the mv64x60
bootwrapper code with lookups by compatible or device_type
properties.
Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
Acked-by: Mark A. Greer <mgreer@mvista.com>
--- a/arch/powerpc/boot/mv64x60.c
+++ b/arch/powerpc/boot/mv64x60.c
@@ -535,7 +535,7 @@ u8 *mv64x60_get_bridge_pbase(void)
u32 v[2];
void *devp;
- devp = finddevice("/mv64x60");
+ devp = find_node_by_compatible(NULL, "mrvl,mv64360");
if (devp == NULL)
goto err_out;
if (getprop(devp, "reg", v, sizeof(v)) != sizeof(v))
@@ -553,7 +553,7 @@ u8 *mv64x60_get_bridge_base(void)
u32 v;
void *devp;
- devp = finddevice("/mv64x60");
+ devp = find_node_by_compatible(NULL, "mrvl,mv64360");
if (devp == NULL)
goto err_out;
if (getprop(devp, "virtual-reg", &v, sizeof(v)) != sizeof(v))
diff --git a/arch/powerpc/boot/mv64x60_i2c.c b/arch/powerpc/boot/mv64x60_i2c.c
index d085377..a69cd7a 100644
--- a/arch/powerpc/boot/mv64x60_i2c.c
+++ b/arch/powerpc/boot/mv64x60_i2c.c
@@ -185,7 +185,7 @@ int mv64x60_i2c_open(void)
u32 v;
void *devp;
- devp = finddevice("/mv64x60/i2c");
+ devp = find_node_by_compatible(NULL, "mrvl,mv64360-i2c");
if (devp == NULL)
goto err_out;
if (getprop(devp, "virtual-reg", &v, sizeof(v)) != sizeof(v))
diff --git a/arch/powerpc/boot/prpmc2800.c b/arch/powerpc/boot/prpmc2800.c
index 05c3245..f74b2cf 100644
--- a/arch/powerpc/boot/prpmc2800.c
+++ b/arch/powerpc/boot/prpmc2800.c
@@ -344,20 +344,20 @@ static void prpmc2800_bridge_setup(u32 mem_size)
acc_bits);
/* Get the cpu -> pci i/o & mem mappings from the device tree */
- devp = finddevice("/mv64x60/pci@80000000");
+ devp = find_node_by_compatible(NULL, "mrvl,mv64360-pci");
if (devp == NULL)
- fatal("Error: Missing /mv64x60/pci@80000000"
+ fatal("Error: Missing mrvl,mv64360-pci"
" device tree node\n\r");
rc = getprop(devp, "ranges", v, sizeof(v));
if (rc != sizeof(v))
- fatal("Error: Can't find /mv64x60/pci@80000000/ranges"
+ fatal("Error: Can't find mrvl,mv64360-pci ranges"
" property\n\r");
/* Get the cpu -> pci i/o & mem mappings from the device tree */
- devp = finddevice("/mv64x60");
+ devp = find_node_by_compatible(NULL, "mrvl,mv64360");
if (devp == NULL)
- fatal("Error: Missing /mv64x60 device tree node\n\r");
+ fatal("Error: Missing mrvl,mv64360 device tree node\n\r");
enables = in_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE));
enables |= 0x0007fe00; /* Disable all cpu->pci windows */
@@ -429,9 +429,9 @@ static void prpmc2800_fixups(void)
setprop(devp, "model", model, l);
/* Set /cpus/PowerPC,7447/clock-frequency */
- devp = finddevice("/cpus/PowerPC,7447");
+ devp = find_node_by_prop_value_str(NULL, "device_type", "cpu");
if (devp == NULL)
- fatal("Error: Missing proper /cpus device tree node\n\r");
+ fatal("Error: Missing proper cpu device tree node\n\r");
v[0] = bip->core_speed;
setprop(devp, "clock-frequency", &v[0], sizeof(v[0]));
@@ -443,16 +443,17 @@ static void prpmc2800_fixups(void)
v[1] = bip->mem_size;
setprop(devp, "reg", v, sizeof(v));
- /* Update /mv64x60/model, if this is a mv64362 */
+ /* Update model, if this is a mv64362 */
if (bip->bridge_type == BRIDGE_TYPE_MV64362) {
- devp = finddevice("/mv64x60");
+ devp = find_node_by_compatible(NULL, "mrvl,mv64360");
if (devp == NULL)
- fatal("Error: Missing /mv64x60 device tree node\n\r");
+ fatal("Error: Missing mrvl,mv64360"
+ " device tree node\n\r");
setprop(devp, "model", "mv64362", strlen("mv64362") + 1);
}
/* Set User FLASH size */
- devp = finddevice("/mv64x60/flash@a0000000");
+ devp = find_node_by_compatible(NULL, "direct-mapped");
if (devp == NULL)
fatal("Error: Missing User FLASH device tree node\n\r");
rc = getprop(devp, "reg", v, sizeof(v));
^ permalink raw reply related
* [PATCH 6/9] [POWERPC] prpmc2800: clean up dts properties
From: Dale Farnsworth @ 2008-03-28 23:49 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20080328233954.GA29499@farnsworth.org>
From: Mark A. Greer <mgreer@mvista.com>
Remove several unused (or software config only) properties.
Rename marvel node to "soc". Technically, it's not an SOC,
but its organization is the same as an SOC. Also, rename the
"block-index" property to "cell-index" to conform to current
practice.
Signed-off-by: Mark A. Greer <mgreer@mvista.com>
Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
Index: linux-2.6/arch/powerpc/boot/dts/prpmc2800.dts
===================================================================
--- linux-2.6.orig/arch/powerpc/boot/dts/prpmc2800.dts
+++ linux-2.6/arch/powerpc/boot/dts/prpmc2800.dts
@@ -42,7 +42,7 @@
reg = <0x0 0x20000000>; /* Default (512MB) */
};
- mv64x60@f1000000 { /* Marvell Discovery */
+ soc@f1000000 { /* Marvell Discovery */
#address-cells = <1>;
#size-cells = <1>;
model = "mv64360"; /* Default */
@@ -114,21 +114,17 @@
};
SDMA0: sdma@4000 {
- device_type = "dma";
compatible = "mrvl,mv64360-sdma";
reg = <0x4000 0xc18>;
virtual-reg = <0xf1004000>;
- interrupt-base = <0>;
interrupts = <36>;
interrupt-parent = <&PIC>;
};
SDMA1: sdma@6000 {
- device_type = "dma";
compatible = "mrvl,mv64360-sdma";
reg = <0x6000 0xc18>;
virtual-reg = <0xf1006000>;
- interrupt-base = <0>;
interrupts = <38>;
interrupt-parent = <&PIC>;
};
@@ -139,7 +135,6 @@
clock-src = <8>;
clock-frequency = <133333333>;
current-speed = <9600>;
- bcr = <0>;
};
BRG1: brg@b208 {
@@ -148,7 +143,6 @@
clock-src = <8>;
clock-frequency = <133333333>;
current-speed = <9600>;
- bcr = <0>;
};
CUNIT: cunit@f200 {
@@ -174,12 +168,7 @@
cunit = <&CUNIT>;
mpscrouting = <&MPSCROUTING>;
mpscintr = <&MPSCINTR>;
- block-index = <0>;
- max_idle = <40>;
- chr_1 = <0>;
- chr_2 = <0>;
- chr_10 = <3>;
- mpcr = <0>;
+ cell-index = <0>;
interrupts = <40>;
interrupt-parent = <&PIC>;
};
@@ -194,12 +183,7 @@
cunit = <&CUNIT>;
mpscrouting = <&MPSCROUTING>;
mpscintr = <&MPSCINTR>;
- block-index = <1>;
- max_idle = <40>;
- chr_1 = <0>;
- chr_2 = <0>;
- chr_10 = <3>;
- mpcr = <0>;
+ cell-index = <1>;
interrupts = <42>;
interrupt-parent = <&PIC>;
};
@@ -207,7 +191,6 @@
wdt@b410 { /* watchdog timer */
compatible = "mrvl,mv64360-wdt";
reg = <0xb410 0x8>;
- timeout = <10>; /* wdt timeout in seconds */
};
i2c@c000 {
@@ -215,10 +198,6 @@
compatible = "mrvl,mv64360-i2c";
reg = <0xc000 0x20>;
virtual-reg = <0xf100c000>;
- freq_m = <8>;
- freq_n = <3>;
- timeout = <1000>; /* 1000 = 1 second */
- retries = <1>;
interrupts = <37>;
interrupt-parent = <&PIC>;
};
Index: linux-2.6/arch/powerpc/boot/mpsc.c
===================================================================
--- linux-2.6.orig/arch/powerpc/boot/mpsc.c
+++ linux-2.6/arch/powerpc/boot/mpsc.c
@@ -141,7 +141,7 @@ int mpsc_console_init(void *devp, struct
if (mpscintr_base == NULL)
goto err_out;
- n = getprop(devp, "block-index", &v, sizeof(v));
+ n = getprop(devp, "cell-index", &v, sizeof(v));
if (n != sizeof(v))
goto err_out;
reg_set = (int)v;
Index: linux-2.6/arch/powerpc/sysdev/mv64x60_dev.c
===================================================================
--- linux-2.6.orig/arch/powerpc/sysdev/mv64x60_dev.c
+++ linux-2.6/arch/powerpc/sysdev/mv64x60_dev.c
@@ -127,7 +127,7 @@ static int __init mv64x60_mpsc_device_se
if (err)
return err;
- prop = of_get_property(np, "block-index", NULL);
+ prop = of_get_property(np, "cell-index", NULL);
if (!prop)
return -ENODEV;
port_number = *(int *)prop;
@@ -136,6 +136,7 @@ static int __init mv64x60_mpsc_device_se
pdata.cache_mgmt = 1; /* All current revs need this set */
+ pdata.max_idle = 40; /* default */
prop = of_get_property(np, "max_idle", NULL);
if (prop)
pdata.max_idle = *prop;
@@ -345,21 +346,19 @@ static int __init mv64x60_i2c_device_set
memset(&pdata, 0, sizeof(pdata));
+ pdata.freq_m = 8; /* default */
prop = of_get_property(np, "freq_m", NULL);
if (!prop)
return -ENODEV;
pdata.freq_m = *prop;
+ pdata.freq_m = 3; /* default */
prop = of_get_property(np, "freq_n", NULL);
if (!prop)
return -ENODEV;
pdata.freq_n = *prop;
- prop = of_get_property(np, "timeout", NULL);
- if (prop)
- pdata.timeout = *prop;
- else
- pdata.timeout = 1000; /* 1 second */
+ pdata.timeout = 1000; /* default: 1 second */
pdev = platform_device_alloc(MV64XXX_I2C_CTLR_NAME, id);
if (!pdev)
@@ -401,10 +400,7 @@ static int __init mv64x60_wdt_device_set
memset(&pdata, 0, sizeof(pdata));
- prop = of_get_property(np, "timeout", NULL);
- if (!prop)
- return -ENODEV;
- pdata.timeout = *prop;
+ pdata.timeout = 10; /* Default: 10 seconds */
np = of_get_parent(np);
if (!np)
@@ -492,7 +488,7 @@ static int __init mv64x60_add_mpsc_conso
if (!of_device_is_compatible(np, "mrvl,mv64360-mpsc"))
goto not_mpsc;
- prop = of_get_property(np, "block-index", NULL);
+ prop = of_get_property(np, "cell-index", NULL);
if (!prop)
goto not_mpsc;
^ permalink raw reply
* [PATCH 7/9] [POWERPC] mv643xx_eth: prepare to support multiple silicon blocks
From: Dale Farnsworth @ 2008-03-28 23:50 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20080328233954.GA29499@farnsworth.org>
From: Dale Farnsworth <dale@farnsworth.org>
The mv643xx_eth driver is being modified to support multiple instances
of the ethernet silicon block on the same platform. Each block contains
a single register bank containing the registers for up to three ports
interleaved within that bank. This patch updates the PowerPC OF to
platform_device glue code to support multiple silicon blocks, each
with up to three ethernet ports. The main difference is that we now
allow multiple mv64x60_shared platform_devices to be registered and
we provide each port platform_device with a pointer to its associated
shared platform_device. The pointer will not be used until the
mv643xx_eth driver changes are committed.
Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
Acked-by: Mark Greer <mgreer@mvista.com>
Index: linux-2.6/arch/powerpc/boot/dts/prpmc2800.dts
===================================================================
--- linux-2.6.orig/arch/powerpc/boot/dts/prpmc2800.dts
+++ linux-2.6/arch/powerpc/boot/dts/prpmc2800.dts
@@ -91,21 +91,24 @@
};
};
- ethernet@2000 {
+ ethernet-group@2000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "mrvl,mv64360-eth-group";
reg = <0x2000 0x2000>;
- eth0 {
+ ethernet@0 {
device_type = "network";
compatible = "mrvl,mv64360-eth";
- block-index = <0>;
+ reg = <0>;
interrupts = <32>;
interrupt-parent = <&PIC>;
phy = <&PHY0>;
local-mac-address = [ 00 00 00 00 00 00 ];
};
- eth1 {
+ ethernet@1 {
device_type = "network";
compatible = "mrvl,mv64360-eth";
- block-index = <1>;
+ reg = <1>;
interrupts = <33>;
interrupt-parent = <&PIC>;
phy = <&PHY1>;
Index: linux-2.6/arch/powerpc/sysdev/mv64x60_dev.c
===================================================================
--- linux-2.6.orig/arch/powerpc/sysdev/mv64x60_dev.c
+++ linux-2.6/arch/powerpc/sysdev/mv64x60_dev.c
@@ -206,30 +206,24 @@ error:
/*
* Create mv64x60_eth platform devices
*/
-static int __init eth_register_shared_pdev(struct device_node *np)
+static struct platform_device * __init mv64x60_eth_register_shared_pdev(
+ struct device_node *np, int id)
{
struct platform_device *pdev;
struct resource r[1];
int err;
- np = of_get_parent(np);
- if (!np)
- return -ENODEV;
-
err = of_address_to_resource(np, 0, &r[0]);
- of_node_put(np);
if (err)
- return err;
+ return ERR_PTR(err);
- pdev = platform_device_register_simple(MV643XX_ETH_SHARED_NAME, 0,
+ pdev = platform_device_register_simple(MV643XX_ETH_SHARED_NAME, id,
r, 1);
- if (IS_ERR(pdev))
- return PTR_ERR(pdev);
-
- return 0;
+ return pdev;
}
-static int __init mv64x60_eth_device_setup(struct device_node *np, int id)
+static int __init mv64x60_eth_device_setup(struct device_node *np, int id,
+ struct platform_device *shared_pdev)
{
struct resource r[1];
struct mv643xx_eth_platform_data pdata;
@@ -240,16 +234,12 @@ static int __init mv64x60_eth_device_set
const phandle *ph;
int err;
- /* only register the shared platform device the first time through */
- if (id == 0 && (err = eth_register_shared_pdev(np)))
- return err;
-
memset(r, 0, sizeof(r));
of_irq_to_resource(np, 0, &r[0]);
memset(&pdata, 0, sizeof(pdata));
- prop = of_get_property(np, "block-index", NULL);
+ prop = of_get_property(np, "reg", NULL);
if (!prop)
return -ENODEV;
pdata.port_number = *prop;
@@ -302,7 +292,7 @@ static int __init mv64x60_eth_device_set
of_node_put(phy);
- pdev = platform_device_alloc(MV643XX_ETH_NAME, pdata.port_number);
+ pdev = platform_device_alloc(MV643XX_ETH_NAME, id);
if (!pdev)
return -ENOMEM;
@@ -437,8 +427,9 @@ error:
static int __init mv64x60_device_setup(void)
{
- struct device_node *np = NULL;
- int id;
+ struct device_node *np, *np2;
+ struct platform_device *pdev;
+ int id, id2;
int err;
id = 0;
@@ -447,9 +438,24 @@ static int __init mv64x60_device_setup(v
goto error;
id = 0;
- for_each_compatible_node(np, "network", "mrvl,mv64360-eth")
- if ((err = mv64x60_eth_device_setup(np, id++)))
+ id2 = 0;
+ for_each_compatible_node(np, NULL, "mrvl,mv64360-eth-group") {
+ pdev = mv64x60_eth_register_shared_pdev(np, id++);
+ if (IS_ERR(pdev)) {
+ err = PTR_ERR(pdev);
goto error;
+ }
+ for_each_child_of_node(np, np2) {
+ if (!of_device_is_compatible(np2,
+ "mrvl,mv64360-eth"))
+ continue;
+ err = mv64x60_eth_device_setup(np2, id2++, pdev);
+ if (err) {
+ of_node_put(np2);
+ goto error;
+ }
+ }
+ }
id = 0;
for_each_compatible_node(np, "i2c", "mrvl,mv64360-i2c")
^ permalink raw reply
* [PATCH 8/9] [POWERPC] Document the mv64x60 device tree bindings
From: Dale Farnsworth @ 2008-03-28 23:51 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20080328233954.GA29499@farnsworth.org>
From: Dale Farnsworth <dale@farnsworth.org>
Add the device tree bindings for the Marvell mv64x60 series of
system controller chips in booting-without-of.text.
Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
Acked-by: Mark A. Greer <mgreer@mvista.com>
Index: linux-2.6/Documentation/powerpc/booting-without-of.txt
===================================================================
--- linux-2.6.orig/Documentation/powerpc/booting-without-of.txt
+++ linux-2.6/Documentation/powerpc/booting-without-of.txt
@@ -57,7 +57,8 @@ Table of Contents
n) 4xx/Axon EMAC ethernet nodes
o) Xilinx IP cores
p) Freescale Synchronous Serial Interface
- q) USB EHCI controllers
+ q) USB EHCI controllers
+ r) Marvell Discovery mv64[345]6x System Controller chips
VII - Specifying interrupt information for devices
1) interrupts property
@@ -2817,6 +2818,471 @@ platforms are moved over to use the flat
};
+ r) Marvell Discovery mv64[345]6x System Controller chips.
+
+ Note that while the Marvell mv64[345]60 series of system controller
+ chips are not true system-on-a-chip processors, they essentially
+ contain the peripheral portion of an SOC and the device tree takes
+ the same form, and we will document them here as if they were an SOC.
+ Compatible string values are prefixed with the string "mrvl,",
+ which is the stock ticker symbol for Marvell Technology Group Ltd.
+
+ An SOC node describes the Marvell chip as described in section III.5.f
+ above.
+
+ Example Marvell Discovery mv64360 SOC node:
+
+ soc@f1000000 { /* Marvell Discovery */
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "mv64360"; /* Default */
+ compatible = "mrvl,mv64360";
+ clock-frequency = <133333333>;
+ reg = <0xf1000000 0x10000>;
+ virtual-reg = <0xf1000000>;
+ ranges = <0x88000000 0x88000000 0x1000000 /* PCI 0 I/O Space */
+ 0x80000000 0x80000000 0x8000000 /* PCI 0 MEM Space */
+ 0xa0000000 0xa0000000 0x4000000 /* User FLASH */
+ 0x00000000 0xf1000000 0x0010000 /* Bridge's regs */
+ 0xf2000000 0xf2000000 0x0040000>;/* Integrated SRAM */
+ }
+
+
+ 1. Marvell Discovery MDIO bus
+
+ The MDIO is a bus to which the PHY devices are connected. For each
+ device that exists on this bus, a child node should be created. See
+ the definition of the PHY node below for an example of how to define
+ a PHY.
+
+ Required properties:
+ - #address-cells : Should be <1>
+ - #size-cells : Should be <0>
+ - device_type : Should be "mdio"
+ - compatible : Should be "mrvl,mv64360-mdio"
+
+ Example:
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ device_type = "mdio";
+ compatible = "mrvl,mv64360-mdio";
+
+ ethernet-phy@0 {
+ ......
+ };
+ };
+
+
+ 2. Marvell Discovery ethernet controller
+
+ The Discover ethernet controller is described with two levels
+ of nodes. The first level describes an ethernet silicon block
+ and the second level describes up to 3 ethernet nodes within
+ that block. The reason for the multiple levels is that the
+ registers for the node are interleaved within a single set
+ of registers. The "ethernet-block" level describes the
+ shared register set, and the "ethernet" nodes describe ethernet
+ port-specific properties.
+
+ Ethernet block node
+
+ Required properties:
+ - #address-cells : <1>
+ - #size-cells : <0>
+ - compatible : "mrvl,mv64360-eth-block"
+ - reg : Offset and length of the register set for this block
+
+ Example Discovery Ethernet block node:
+ ethernet-block@2000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "mrvl,mv64360-eth-block";
+ reg = <0x2000 0x2000>;
+ ethernet@0 {
+ .......
+ };
+ };
+
+ Ethernet port node
+
+ Required properties:
+ - device_type : Should be "network".
+ - compatible : Should be "mrvl,mv64360-eth".
+ - reg : Should be <0>, <1>, or <2>, according to which registers
+ within the silicon block the device uses.
+ - interrupts : <a> where a is the interrupt number for the port.
+ - interrupt-parent : the phandle for the interrupt controller
+ that services interrupts for this device.
+ - phy : the phandle for the PHY connected to this ethernet
+ controller.
+ - local-mac-address : 6 bytes, MAC address
+
+ Example Discovery Ethernet port node:
+ ethernet@0 {
+ device_type = "network";
+ compatible = "mrvl,mv64360-eth";
+ reg = <0>;
+ interrupts = <32>;
+ interrupt-parent = <&PIC>;
+ phy = <&PHY0>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+
+
+
+ 3. Marvell Discovery PHY nodes
+
+ Required properties:
+ - device_type : Should be "ethernet-phy"
+ - interrupts : <a> where a is the interrupt number for this phy.
+ - interrupt-parent : the phandle for the interrupt controller that
+ services interrupts for this device.
+ - reg : The ID number for the phy, usually a small integer
+
+ Example Discovery PHY node:
+ ethernet-phy@1 {
+ device_type = "ethernet-phy";
+ compatible = "broadcom,bcm5421";
+ interrupts = <76>; /* GPP 12 */
+ interrupt-parent = <&PIC>;
+ reg = <1>;
+ };
+
+
+
+ 4. Marvell Discovery SDMA nodes
+ Represent DMA hardware associated with the MPSC (multiprotocol
+ serial controllers).
+
+ Required properties:
+ - compatible : "mrvl,mv64360-sdma"
+ - reg : Offset and length of the register set for this device
+ - interrupts : <a> where a is the interrupt number for the DMA
+ device.
+ - interrupt-parent : the phandle for the interrupt controller
+ that services interrupts for this device.
+
+ Example Discovery SDMA node:
+ sdma@4000 {
+ compatible = "mrvl,mv64360-sdma";
+ reg = <0x4000 0xc18>;
+ virtual-reg = <0xf1004000>;
+ interrupts = <36>;
+ interrupt-parent = <&PIC>;
+ };
+
+
+ 5. Marvell Discovery BRG nodes
+ Represent baud rate generator hardware associated with the MPSC
+ (multiprotocol serial controllers).
+
+ Required properties:
+ - compatible : "mrvl,mv64360-brg"
+ - reg : Offset and length of the register set for this device
+ - clock-src : A value from 0 to 15 which selects the clock
+ source for the baud rate generator. This value corresponds
+ to the CLKS value in the BRGx configuration register. See
+ the mv64x60 User's Manual.
+ - clock-frequence : The frequency (in Hz) of the baud rate
+ generator's input clock.
+ - current-speed : The current speed setting (presumably by
+ firmware) of the baud rate generator.
+
+ Example Discovery BRG node:
+ brg@b200 {
+ compatible = "mrvl,mv64360-brg";
+ reg = <0xb200 0x8>;
+ clock-src = <8>;
+ clock-frequency = <133333333>;
+ current-speed = <9600>;
+ };
+
+
+ 6. Marvell Discovery CUNIT nodes
+ Represent the Serial Communications Unit device hardware.
+
+ Required properties:
+ - reg : Offset and length of the register set for this device
+
+ Example Discovery CUNIT node:
+ cunit@f200 {
+ reg = <0xf200 0x200>;
+ };
+
+
+ 7. Marvell Discovery MPSCROUTING nodes
+ Represent the Discovery's MPSC routing hardware
+
+ Required properties:
+ - reg : Offset and length of the register set for this device
+
+ Example Discovery CUNIT node:
+ mpscrouting@b500 {
+ reg = <0xb400 0xc>;
+ };
+
+
+ 8. Marvell Discovery MPSCINTR nodes
+ Represent the Discovery's MPSC DMA interrupt hardware registers
+ (SDMA cause and mask registers).
+
+ Required properties:
+ - reg : Offset and length of the register set for this device
+
+ Example Discovery MPSCINTR node:
+ mpsintr@b800 {
+ reg = <0xb800 0x100>;
+ };
+
+
+ 9. Marvell Discovery MPSC nodes
+ Represent the Discovery's MPSC (Multiprotocol Serial Controller)
+ serial port.
+
+ Required properties:
+ - device_type : "serial"
+ - compatible : "mrvl,mv64360-mpsc"
+ - reg : Offset and length of the register set for this device
+ - sdma : the phandle for the SDMA node used by this port
+ - brg : the phandle for the BRG node used by this port
+ - cunit : the phandle for the CUNIT node used by this port
+ - mpscrouting : the phandle for the MPSCROUTING node used by this port
+ - mpscintr : the phandle for the MPSCINTR node used by this port
+ - cell-index : the hardware index of this cell in the MPSC core
+ - max_idle : value needed for MPSC CHR3 (Maximum Frame Length)
+ register
+ - interrupts : <a> where a is the interrupt number for the MPSC.
+ - interrupt-parent : the phandle for the interrupt controller
+ that services interrupts for this device.
+
+ Example Discovery MPSCINTR node:
+ mpsc@8000 {
+ device_type = "serial";
+ compatible = "mrvl,mv64360-mpsc";
+ reg = <0x8000 0x38>;
+ virtual-reg = <0xf1008000>;
+ sdma = <&SDMA0>;
+ brg = <&BRG0>;
+ cunit = <&CUNIT>;
+ mpscrouting = <&MPSCROUTING>;
+ mpscintr = <&MPSCINTR>;
+ cell-index = <0>;
+ max_idle = <40>;
+ interrupts = <40>;
+ interrupt-parent = <&PIC>;
+ };
+
+
+ 10. Marvell Discovery Watch Dog Timer nodes
+ Represent the Discovery's watchdog timer hardware
+
+ Required properties:
+ - compatible : "mrvl,mv64360-wdt"
+ - reg : Offset and length of the register set for this device
+
+ Example Discovery Watch Dog Timer node:
+ wdt@b410 {
+ compatible = "mrvl,mv64360-wdt";
+ reg = <0xb410 0x8>;
+ };
+
+
+ 11. Marvell Discovery I2C nodes
+ Represent the Discovery's I2C hardware
+
+ Required properties:
+ - device_type : "i2c"
+ - compatible : "mrvl,mv64360-i2c"
+ - reg : Offset and length of the register set for this device
+ - interrupts : <a> where a is the interrupt number for the I2C.
+ - interrupt-parent : the phandle for the interrupt controller
+ that services interrupts for this device.
+
+ Example Discovery I2C node:
+ compatible = "mrvl,mv64360-i2c";
+ reg = <0xc000 0x20>;
+ virtual-reg = <0xf100c000>;
+ interrupts = <37>;
+ interrupt-parent = <&PIC>;
+ };
+
+
+ 12. Marvell Discovery PIC (Programmable Interrupt Controller) nodes
+ Represent the Discovery's PIC hardware
+
+ Required properties:
+ - #interrupt-cells : <1>
+ - #address-cells : <0>
+ - compatible : "mrvl,mv64360-pic"
+ - reg : Offset and length of the register set for this device
+ - interrupt-controller
+
+ Example Discovery PIC node:
+ pic {
+ #interrupt-cells = <1>;
+ #address-cells = <0>;
+ compatible = "mrvl,mv64360-pic";
+ reg = <0x0 0x88>;
+ interrupt-controller;
+ };
+
+
+ 13. Marvell Discovery MPP (Multipurpose Pins) multiplexing nodes
+ Represent the Discovery's MPP hardware
+
+ Required properties:
+ - compatible : "mrvl,mv64360-mpp"
+ - reg : Offset and length of the register set for this device
+
+ Example Discovery MPP node:
+ mpp@f000 {
+ compatible = "mrvl,mv64360-mpp";
+ reg = <0xf000 0x10>;
+ };
+
+
+ 14. Marvell Discovery GPP (General Purpose Pins) nodes
+ Represent the Discovery's GPP hardware
+
+ Required properties:
+ - compatible : "mrvl,mv64360-gpp"
+ - reg : Offset and length of the register set for this device
+
+ Example Discovery GPP node:
+ gpp@f000 {
+ compatible = "mrvl,mv64360-gpp";
+ reg = <0xf100 0x20>;
+ };
+
+
+ 15. Marvell Discovery PCI host bridge node
+ Represents the Discovery's PCI host bridge device. The properties
+ for this node conform to Rev 2.1 of the PCI Bus Binding to IEEE
+ 1275-1994. A typical value for the compatible property is
+ "mrvl,mv64360-pci".
+
+ Example Discovery PCI host bridge node
+ pci@80000000 {
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ device_type = "pci";
+ compatible = "mrvl,mv64360-pci";
+ reg = <0xcf8 0x8>;
+ ranges = <0x01000000 0x0 0x0
+ 0x88000000 0x0 0x01000000
+ 0x02000000 0x0 0x80000000
+ 0x80000000 0x0 0x08000000>;
+ bus-range = <0 255>;
+ clock-frequency = <66000000>;
+ interrupt-parent = <&PIC>;
+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x0a */
+ 0x5000 0 0 1 &PIC 80
+ 0x5000 0 0 2 &PIC 81
+ 0x5000 0 0 3 &PIC 91
+ 0x5000 0 0 4 &PIC 93
+
+ /* IDSEL 0x0b */
+ 0x5800 0 0 1 &PIC 91
+ 0x5800 0 0 2 &PIC 93
+ 0x5800 0 0 3 &PIC 80
+ 0x5800 0 0 4 &PIC 81
+
+ /* IDSEL 0x0c */
+ 0x6000 0 0 1 &PIC 91
+ 0x6000 0 0 2 &PIC 93
+ 0x6000 0 0 3 &PIC 80
+ 0x6000 0 0 4 &PIC 81
+
+ /* IDSEL 0x0d */
+ 0x6800 0 0 1 &PIC 93
+ 0x6800 0 0 2 &PIC 80
+ 0x6800 0 0 3 &PIC 81
+ 0x6800 0 0 4 &PIC 91
+ >;
+ };
+
+
+ 16. Marvell Discovery CPU Error nodes
+ Represent the Discovery's CPU error handler device.
+
+ Required properties:
+ - compatible : "mrvl,mv64360-cpu-error"
+ - reg : Offset and length of the register set for this device
+ - interrupts : the interrupt number for this device
+ - interrupt-parent : the phandle for the interrupt controller
+ that services interrupts for this device.
+
+ Example Discovery CPU Error node:
+ cpu-error@0070 {
+ compatible = "mrvl,mv64360-cpu-error";
+ reg = <0x70 0x10 0x128 0x28>;
+ interrupts = <3>;
+ interrupt-parent = <&PIC>;
+ };
+
+
+ 17. Marvell Discovery SRAM Controller nodes
+ Represent the Discovery's SRAM controller device.
+
+ Required properties:
+ - compatible : "mrvl,mv64360-sram-ctrl"
+ - reg : Offset and length of the register set for this device
+ - interrupts : the interrupt number for this device
+ - interrupt-parent : the phandle for the interrupt controller
+ that services interrupts for this device.
+
+ Example Discovery SRAM Controller node:
+ sram-ctrl@0380 {
+ compatible = "mrvl,mv64360-sram-ctrl";
+ reg = <0x380 0x80>;
+ interrupts = <13>;
+ interrupt-parent = <&PIC>;
+ };
+
+
+ 18. Marvell Discovery PCI Error Handler nodes
+ Represent the Discovery's PCI error handler device.
+
+ Required properties:
+ - compatible : "mrvl,mv64360-pci-error"
+ - reg : Offset and length of the register set for this device
+ - interrupts : the interrupt number for this device
+ - interrupt-parent : the phandle for the interrupt controller
+ that services interrupts for this device.
+
+ Example Discovery PCI Error Handler node:
+ pci-error@1d40 {
+ compatible = "mrvl,mv64360-pci-error";
+ reg = <0x1d40 0x40 0xc28 0x4>;
+ interrupts = <12>;
+ interrupt-parent = <&PIC>;
+ };
+
+
+ 19. Marvell Discovery Memory Controller nodes
+ Represent the Discovery's memory controller device.
+
+ Required properties:
+ - compatible : "mrvl,mv64360-mem-ctrl"
+ - reg : Offset and length of the register set for this device
+ - interrupts : the interrupt number for this device
+ - interrupt-parent : the phandle for the interrupt controller
+ that services interrupts for this device.
+
+ Example Discovery Memory Controller node:
+ mem-ctrl@1400 {
+ compatible = "mrvl,mv64360-mem-ctrl";
+ reg = <0x1400 0x60>;
+ interrupts = <17>;
+ interrupt-parent = <&PIC>;
+ };
+
+
More devices will be defined as this spec matures.
VII - Specifying interrupt information for devices
^ permalink raw reply
* [PATCH 9/9] [POWERPC] prpmc2800 needs a dtbImage
From: Dale Farnsworth @ 2008-03-28 23:52 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20080328233954.GA29499@farnsworth.org>
From: Dale Farnsworth <dale@farnsworth.org>
The prpmc2800 platform requires a zImage formatted file with an
embedded dtb file. Rename the requested boot image file to
dtbImage.prpmc2800.
Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
Acked-by: Mark A. Greer <mgreer@mvista.com>
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -192,7 +192,7 @@ image-$(CONFIG_PPC_CHRP) += zImage.chrp
image-$(CONFIG_PPC_EFIKA) += zImage.chrp
image-$(CONFIG_PPC_PMAC) += zImage.pmac
image-$(CONFIG_PPC_HOLLY) += zImage.holly
-image-$(CONFIG_PPC_PRPMC2800) += zImage.prpmc2800
+image-$(CONFIG_PPC_PRPMC2800) += dtbImage.prpmc2800
image-$(CONFIG_PPC_ISERIES) += zImage.iseries
image-$(CONFIG_DEFAULT_UIMAGE) += uImage
^ permalink raw reply
* Re: [PATCH 9/9] [POWERPC] prpmc2800 needs a dtbImage
From: Grant Likely @ 2008-03-28 23:56 UTC (permalink / raw)
To: Dale Farnsworth; +Cc: linuxppc-dev, paulus
In-Reply-To: <20080328235213.GI30214@farnsworth.org>
On Fri, Mar 28, 2008 at 5:52 PM, Dale Farnsworth <dale@farnsworth.org> wrote:
> From: Dale Farnsworth <dale@farnsworth.org>
>
> The prpmc2800 platform requires a zImage formatted file with an
> embedded dtb file. Rename the requested boot image file to
> dtbImage.prpmc2800.
>
> Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
> Acked-by: Mark A. Greer <mgreer@mvista.com>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
>
> --- a/arch/powerpc/boot/Makefile
> +++ b/arch/powerpc/boot/Makefile
> @@ -192,7 +192,7 @@ image-$(CONFIG_PPC_CHRP) += zImage.chrp
> image-$(CONFIG_PPC_EFIKA) += zImage.chrp
> image-$(CONFIG_PPC_PMAC) += zImage.pmac
> image-$(CONFIG_PPC_HOLLY) += zImage.holly
> -image-$(CONFIG_PPC_PRPMC2800) += zImage.prpmc2800
> +image-$(CONFIG_PPC_PRPMC2800) += dtbImage.prpmc2800
> image-$(CONFIG_PPC_ISERIES) += zImage.iseries
> image-$(CONFIG_DEFAULT_UIMAGE) += uImage
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Linux 2.6 PCI Device Driver on Virtex 4
From: Huang, Bin @ 2008-03-28 23:42 UTC (permalink / raw)
To: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 6580 bytes --]
I have spent the past few months slowly trying to get a PCI design
with Linux 2.6 on the Virtex 4. I have been able to overcome some of
the hurdles; however, I am still unable to boot up a working system.
I am using PPC.I have implemented Xilinx's board support package including
xparameter head file, ml410 early boot files, pci support files,
Board initialization file, did board specific setup, and fixed some
bugs in its call tree.
I have attached my booting message in this mail. As you can see, I am
stuck at "[ 11.805382] Freeing unused kernel memory: 100k init" . Usually
it's the last step before the kernel starts root file system. I am sure my ramdisk and
root file system were both working OK. My naive thought is that the kernel could not
register serial port successfully (see time stamp [ 5.965954]). As a result, ttyS0 was
not able to run and display messages after starting ramdisk.
It's also interesting to see my ml410 board respond me with a "ml300"
id. My booting message was saying:
pci_scan: bus 0, device 8, id 030010ee
"10ee" is the vendor id for xilinx while "0300" is the device id which
I think might represent ml300. Does Xilinx forget to refresh its rom?
Here is my environment and tools:
-- Xilinx ML410 Rev C
-- Xilinx EDK 9.2i
-- Secret lab Linux v2.6 originally configured as platform Xilinx
ML403
And my booting message:
---------------------------------------------------------------------------
Xilinx ML410 Board-Specific Initialization:
ppb_init: dev = 9, id = ac23104c
pci_scan: bus 0, device 1, id 545110b9
pci_scan: bus 0, device 2, id 153310b9
pci_scan: bus 0, device 3, id 545710b9
pci_scan: bus 0, device 8, id 030010ee
pci_scan: bus 0, device 9, id ac23104c
pci_scan: bus 0, device 12, id 710110b9
pci_scan: bus 0, device 15, id 523710b9
sio_init: Device ID = 53 15, Revision = f3.
sio_init: LPT1 base = 0x0378, irq = 5.
sio_init: COM1 base = 0x03f8, irq = 4.
sio_init: COM2 base = 0x02f8, irq = 3.
sio_init: KBC irq = 1, PS2 irq = 1.
sio_init: Super I/O initialization complete.
loaded at: 00400000 006C21B4
board data at: 006C0124 006C01A0
relocated to: 00405154 004051D0
zimage at: 00406215 004EFDAA
initrd at: 004F0000 006BFDB0
avail ram: 006C3000 08000000
Linux/PPC load: console=ttyS0,9600 ip=off root=/dev/ram
Uncompressing Linux...done.
Now booting the kernel
[ 0.000000] Linux version 2.6.23-rc2-g0d62d8a8-dirty (bhuang2@rsass-
homer.uncc.edu) (gcc version 4.2.1) #190 Thu Mar 28
[ 0.000000] Xilinx ML40x Reference System (Virtex-4 FX)
[ 0.000000] Port by MontaVista Software, Inc. (sou...@mvista.com)
[ 0.000000] Zone PFN ranges:
[ 0.000000] DMA 0 -> 32768
[ 0.000000] Normal 32768 -> 32768
[ 0.000000] Movable zone start PFN for each node
[ 0.000000] early_node_map[1] active PFN ranges
[ 0.000000] 0: 0 -> 32768
[ 0.000000] Built 1 zonelists in Zone order. Total pages: 32512
[ 0.000000] Kernel command line: console=ttyS0,9600 ip=off root=/
dev/ram
[ 0.000000] Xilinx INTC #0 at 0x41200000 mapped to 0xE7FED000
[ 0.000000] PID hash table entries: 512 (order: 9, 2048 bytes)
[ 0.000175] Console: colour dummy device 80x25
[ 0.000241] console [ttyS0] enabled
[ 1.382947] Dentry cache hash table entries: 16384 (order: 4, 65536
bytes)
[ 1.466045] Inode-cache hash table entries: 8192 (order: 3, 32768
bytes)
[ 1.572643] Memory: 125852k available (1480k kernel code, 496k
data, 100k init, 0k highmem)
[ 1.764350] Mount-cache hash table entries: 512
[ 1.827727] PCI: Probing PCI hardware
[ 1.906477] ppc405_map_irq: bus 0 idsel 1 pin 1, res = 31
[ 1.970528] ppc405_map_irq: bus 0 idsel 2 pin 1, res = 31
[ 2.035157] ppc405_map_irq: bus 0 idsel 3 pin 1, res = 31
[ 2.099646] ppc405_map_irq: bus 0 idsel 8 pin 1, res = 31
[ 2.164225] ppc405_map_irq: bus 0 idsel 9 pin 1, res = 31
[ 2.228787] ppc405_map_irq: bus 0 idsel 11 pin 1, res = 31
[ 2.294400] ppc405_map_irq: bus 0 idsel 12 pin 1, res = 31
[ 2.360031] ppc405_map_irq: bus 0 idsel 15 pin 1, res = 31
[ 2.441645] SCSI subsystem initialized
[ 2.487503] usbcore: registered new interface driver usbfs
[ 2.553907] usbcore: registered new interface driver hub
[ 2.617790] usbcore: registered new device driver usb
[ 2.687574] checking if image is initramfs...it isn't (no cpio
magic); looks like an initrd
[ 4.548936] Freeing initrd memory: 1855k freed
[ 4.606889] io scheduler noop registered
[ 4.653232] io scheduler anticipatory registered (default)
[ 4.718790] io scheduler deadline registered
[ 4.769907] io scheduler cfq registered
[ 4.815634] Activating ISA DMA hang workarounds.
[ 5.667502] 0000:00:0f.0 OHCI: BIOS handoff failed (BIOS bug ?)
ffffffff
[ 5.798505] Serial: 8250/16550 driver $Revision: 1.90 $ 1 ports,
IRQ sharing disabled
[ 5.892194] serial8250: ttyS0 at MMIO 0x0 (irq = 12) is a 16550A
[ 5.965954] Couldn't register serial port 0000:00:03.0: -28
[ 6.044910] RAMDISK driver initialized: 16 RAM disks of 65536K size
1024 blocksize
[ 6.141529] loop: module loaded
[ 6.178422] Uniform Multi-Platform E-IDE driver Revision:
7.00alpha2
[ 6.254522] ide: Assuming 33MHz system bus speed for PIO modes;
override with idebus=xx
[ 6.351314] ALI15X3: IDE controller at PCI slot 0000:00:0b.0
[ 6.418510] ALI15X3: chipset revision 196
[ 6.466414] ALI15X3: 100% native mode on irq 31
[ 6.520489] ALI15X3: simplex device: DMA forced
[ 6.574602] ide0: BM-DMA at 0xdfd0-0xdfd7, BIOS settings:
hda:DMA, hdb:DMA
[ 6.660918] ALI15X3: simplex device: DMA forced
[ 6.715201] ide1: BM-DMA at 0xdfd8-0xdfdf, BIOS settings:
hdc:DMA, hdd:DMA
[ 9.054991] usbmon: debugfs is not available
[ 9.106161] mice: PS/2 mouse device common for all mice
[ 9.168819] ali15x3_smbus 0000:00:0c.0: ALI15X3_smb region
uninitialized - upgrade BIOS or use force_addr=0xaddr
[ 9.290327] ali15x3_smbus 0000:00:0c.0: ALI15X3 not detected,
module not inserted.
[ 9.383605] RAMDISK: Compressed image found at block 0
[ 11.704980] VFS: Mounted root (ext2 filesystem) readonly.
[ 11.805382] Freeing unused kernel memory: 100k init
................kernel stops here................
---------------------------------------------------------------------------
If anyone has tried to do this (or has already done this) I would
apprecaite any help or suggestions.
regards,
Bin
[-- Attachment #2: Type: text/html, Size: 8913 bytes --]
^ permalink raw reply
* Re: [PATCH 1/9] [POWERPC] mv64x60: change FDT compatible prefix to mrvl
From: Dale Farnsworth @ 2008-03-29 0:00 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-dev, paulus
In-Reply-To: <fa686aa40803281647y4ccc4605n1507f9c1868d4c0f@mail.gmail.com>
On Fri, Mar 28, 2008 at 05:47:25PM -0600, Grant Likely wrote:
> On Fri, Mar 28, 2008 at 5:42 PM, Dale Farnsworth <dale@farnsworth.org> wrote:
> > From: Dale Farnsworth <dale@farnsworth.org>
> >
> > Follow the convention that compatible names are prefixed by the
> > vendor's stock ticker symbol. For Marvell Technology Group Ltd.,
> > that's MRVL.
> >
> > Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
> > Acked-by: Mark A. Greer <mgreer@mvista.com>
>
> Are there any boards "in the wild" using the old string? If so are
> does changing this string risk complicating upgrades to a new kernel
> version?
I don't think this complicates things much, since all these boards boot
a dtbImage, with an embedded dtb file built from the kernel source.
So the dts and code don't have much opportunity to get out of sync.
-Dale
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox