* [PATCH 17/17] Add the memory mapping support in rionet driver.
From: Zhang Wei @ 2008-03-11 9:07 UTC (permalink / raw)
To: mporter, akpm, galak; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <1205226478-7641-16-git-send-email-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>
---
drivers/net/Kconfig | 10 ++
drivers/net/rionet.c | 324 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 334 insertions(+), 0 deletions(-)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index a0f0e60..bc46704 100644
--- a/drivers/net/Kconfig
+++ b/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 --git a/drivers/net/rionet.c b/drivers/net/rionet.c
index 2b8fd68..bdc33c4 100644
--- a/drivers/net/rionet.c
+++ b/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_device *ndev)
rnet->rx_skb[i]->data = data;
skb_put(rnet->rx_skb[i], RIO_MAX_MSG_SIZE);
+ rnet->rx_skb[i]->dev = ndev;
rnet->rx_skb[i]->protocol =
eth_type_trans(rnet->rx_skb[i], ndev);
error = netif_rx(rnet->rx_skb[i]);
+ rnet->rx_skb[i] = NULL;
if (error == NET_RX_DROP) {
ndev->stats.rx_dropped++;
@@ -128,6 +186,7 @@ static int rionet_rx_clean(struct net_device *ndev)
return i;
}
+#endif
static void rionet_rx_fill(struct net_device *ndev, int end)
{
@@ -141,19 +200,94 @@ static void rionet_rx_fill(struct net_device *ndev, int end)
if (!rnet->rx_skb[i])
break;
+#ifndef CONFIG_RIONET_MEMMAP
rio_add_inb_buffer(rnet->mport, RIONET_MAILBOX,
rnet->rx_skb[i]->data);
+#endif
} while ((i = (i + 1) % RIONET_RX_RING_SIZE) != end);
rnet->rx_slot = i;
}
+#ifdef CONFIG_RIONET_MEMMAP
+static int rio_send_mem(struct sk_buff *skb,
+ struct net_device *ndev, struct rio_dev *rdev)
+{
+ struct rionet_private *rnet = 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_buff *skb, struct net_device *ndev,
++rnet->tx_slot;
rnet->tx_slot &= (RIONET_TX_RING_SIZE - 1);
+#ifdef CONFIG_RIONET_MEMMAP
+ while (rnet->tx_cnt && (rnet->ack_slot != rnet->tx_slot)) {
+ /* dma unmap single */
+ dev_kfree_skb_any(rnet->tx_skb[rnet->ack_slot]);
+ rnet->tx_skb[rnet->ack_slot] = NULL;
+ ++rnet->ack_slot;
+ rnet->ack_slot &= (RIONET_TX_RING_SIZE - 1);
+ rnet->tx_cnt--;
+ }
+
+ if (rnet->tx_cnt < RIONET_TX_RING_SIZE)
+ netif_wake_queue(ndev);
+#endif
if (netif_msg_tx_queued(rnet))
printk(KERN_INFO "%s: queued skb %8.8x len %8.8x\n", DRV_NAME,
(u32) skb, skb->len);
@@ -211,6 +358,93 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
return 0;
}
+#ifdef CONFIG_RIONET_MEMMAP
+static void rio_recv_mem(struct net_device *ndev)
+{
+ struct rionet_private *rnet = (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 rio_mport *mport, void *dev_id, u16 sid, u
}
} else if (info == RIONET_DOORBELL_LEAVE) {
rionet_active[sid] = NULL;
+#ifdef CONFIG_RIONET_MEMMAP
+ } else if (info == RIONET_DOORBELL_SEND) {
+ rionet_inb_recv_event(mport, ndev);
+#endif
} else {
if (netif_msg_intr(rnet))
printk(KERN_WARNING "%s: unhandled doorbell\n",
@@ -239,6 +477,7 @@ static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u
}
}
+#ifndef CONFIG_RIONET_MEMMAP
static void rionet_inb_msg_event(struct rio_mport *mport, void *dev_id, int mbox, int slot)
{
int n;
@@ -281,6 +520,58 @@ static void rionet_outb_msg_event(struct rio_mport *mport, void *dev_id, int mbo
spin_unlock(&rnet->lock);
}
+#endif
+
+#ifdef CONFIG_RIONET_DMA
+static enum dma_state_client rionet_dma_event(struct dma_client *client,
+ struct dma_chan *chan, enum dma_state state)
+{
+ struct rionet_private *rnet = container_of(client,
+ struct rionet_private, rio_dma_client);
+ enum dma_state_client ack = DMA_DUP;
+
+ spin_lock(&rnet->lock);
+ switch (state) {
+ case DMA_RESOURCE_AVAILABLE:
+ if (!rnet->txdmachan) {
+ ack = DMA_ACK;
+ rnet->txdmachan = chan;
+ } else if (!rnet->rxdmachan) {
+ ack = DMA_ACK;
+ rnet->rxdmachan = chan;
+ }
+ break;
+ case DMA_RESOURCE_REMOVED:
+ if (rnet->txdmachan == chan) {
+ ack = DMA_ACK;
+ rnet->txdmachan = NULL;
+ } else if (rnet->rxdmachan == chan) {
+ ack = DMA_ACK;
+ rnet->rxdmachan = NULL;
+ }
+ break;
+ default:
+ break;
+ }
+ spin_unlock(&rnet->lock);
+ return ack;
+}
+
+static int rionet_dma_register(struct rionet_private *rnet)
+{
+ int rc = 0;
+ spin_lock_init(&rnet->rio_dma_event_lock);
+ rnet->rio_dma_client.event_callback = rionet_dma_event;
+ dma_cap_set(DMA_MEMCPY, rnet->rio_dma_client.cap_mask);
+ dma_async_client_register(&rnet->rio_dma_client);
+ dma_async_client_chan_request(&rnet->rio_dma_client);
+
+ if (!rnet->txdmachan || !rnet->rxdmachan)
+ rc = -ENODEV;
+
+ return rc;
+}
+#endif
static int rionet_open(struct net_device *ndev)
{
@@ -299,6 +590,28 @@ static int rionet_open(struct net_device *ndev)
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 *ndev)
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_device *ndev)
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;
}
--
1.5.4
^ permalink raw reply related
* [PATCH 14/17] Add the RapidIO master port maintance and doorbell window to space resources.
From: Zhang Wei @ 2008-03-11 9:07 UTC (permalink / raw)
To: mporter, akpm, galak; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <1205226478-7641-13-git-send-email-wei.zhang@freescale.com>
Add the RapidIO master port maintance and doorbell IO windows to
RIO space resources.
Signed-off-by: Zhang Wei <wei.zhang@freescale.com>
---
arch/powerpc/sysdev/fsl_rio.c | 26 +++++++++++++++++++++-----
include/linux/rio.h | 1 +
2 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index 917eed0..656f754 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -192,6 +192,8 @@ struct rio_priv {
int bellirq;
int txirq;
int rxirq;
+ struct resource maint_res;
+ struct resource dbell_res;
};
/**
@@ -1362,15 +1364,29 @@ int fsl_rio_setup(struct of_device *dev)
out_be32((priv->regs_win + RIO_ISR_AACR), RIO_ISR_AACR_AA);
/* Configure maintenance transaction window */
- out_be32(&priv->maint_atmu_regs->rowbar, 0x000c0000);
- out_be32(&priv->maint_atmu_regs->rowar, 0x80077015);
+ rio_init_io_res(&priv->maint_res, law_start, RIO_MAINT_WIN_SIZE,
+ "maint_win", RIO_RESOURCE_MAINT);
+ rc = rio_request_io_region(port, &priv->maint_res);
+ if (rc) {
+ dev_err(&dev->dev, "request maint window error!\n");
+ goto err;
+ }
+ out_be32(&priv->maint_atmu_regs->rowbar, (law_start >> 12) & 0xffffff);
+ out_be32(&priv->maint_atmu_regs->rowar, 0x80077000
+ | (__ilog2(RIO_MAINT_WIN_SIZE) - 1));
priv->maint_win = ioremap(law_start, RIO_MAINT_WIN_SIZE);
/* Configure outbound doorbell window */
- out_be32(&priv->dbell_atmu_regs->rowbar, 0x000c0400);
- out_be32(&priv->dbell_atmu_regs->rowar, 0x8004200b);
- fsl_rio_doorbell_init(port);
+ rio_init_io_res(&priv->dbell_res, law_start + RIO_MAINT_WIN_SIZE,
+ RIO_DBELL_WIN_SIZE, "dbell_win", RIO_RESOURCE_DOORBELL);
+ out_be32(&priv->dbell_atmu_regs->rowbar, (priv->dbell_res.start >> 12)
+ & 0xffffff);
+ out_be32(&priv->dbell_atmu_regs->rowar, 0x80042000
+ | (__ilog2(RIO_DBELL_WIN_SIZE) - 1));
+ rc = fsl_rio_doorbell_init(port);
+ if (rc)
+ goto err;
return 0;
err:
diff --git a/include/linux/rio.h b/include/linux/rio.h
index 15a008b..93ca55d 100644
--- a/include/linux/rio.h
+++ b/include/linux/rio.h
@@ -257,6 +257,7 @@ struct rio_ops {
#define RIO_RESOURCE_MEM 0x00000100
#define RIO_RESOURCE_DOORBELL 0x00000200
#define RIO_RESOURCE_MAILBOX 0x00000400
+#define RIO_RESOURCE_MAINT 0x00000800
#define RIO_RESOURCE_CACHEABLE 0x00010000
#define RIO_RESOURCE_PCI 0x00020000
--
1.5.4
^ permalink raw reply related
* Re: OF compatible MTD platform RAM driver ?
From: Laurent Pinchart @ 2008-03-11 10:39 UTC (permalink / raw)
To: David Gibson; +Cc: ben, linuxppc-dev, linux-mtd
In-Reply-To: <20080311004545.GI11559@localhost.localdomain>
[-- Attachment #1: Type: text/plain, Size: 2407 bytes --]
On Tuesday 11 March 2008 01:45, David Gibson wrote:
> On Mon, Mar 10, 2008 at 12:00:22PM -0500, Rune Torgersen wrote:
> > linuxppc-dev-bounces+runet=innovsys.com@ozlabs.org wrote:
> > > Hi everybody,
> > >
> > > as part of a ARCH=ppc to ARCH=powerpc migration process, I'm
> > > looking for an
> > > OpenFirmware compatible way to handle a RAM-based MTD device.
> > >
> > > On the platform_device based ppc architecture, the
> > > drivers/mtd/maps/plat-ram.c
> > > driver handled "mtd-ram" platform devices. There is no such
> > > driver for the
> > > OF-based powerpc architecture.
> > >
> > > As a temporary workaround I hacked the physmap_of driver to
> > > handle "direct-mapped" OF devices oh type "ram" by adding a
> > > corresponding entry in the of_flash_match[] array. This seems to work
> > > fine.
> > >
> > > What would be the preferred way to handle OF-compatible RAM-based MTD
> > > devices ? The 3 ways I can think of are
> > >
> > > 1. porting the plat-ram driver to OF (the driver isn't used
> > > in the kernel tree
> > > but I suspect it is used by out-of-tree boards)
> > >
> > > 2. creating a new plat-ram-of driver, much like the
> > > physmap_of driver comes
> > > from the physmap driver
> > >
> > > 3. extending the physmap_of driver to handle RAM devices (in
> > > which case
> > > references to "flash" in the function names should probably
> > > be replaced
> > > by "mtd")
> > >
> > > I live option 3 better so far.
> > >
> > > Has anyone already worked on this ? Is there any defined
> > > device tree mapping
> > > for MTD RAM devices ?
> >
> > We ran ito the same issue.
> > We did option 3, as it was efinetly the easiest,
>
> I think this is the best option in principle.
I'll implement that and post a patch after completing the ppc-to-powerpc
migration.
> > here is the sram entry in our dts:
>
> Except that your implementation of it is not good.
>
> You're relying on the old obsolete flash binding with the "probe-type"
> field. The solution should be adapted to the new approach which uses
> values in the "compatible" field to indicate various sorts of flash
> device.
What "compatible" values should I use for ROM and RAM mappings ?
Best regards,
--
Laurent Pinchart
CSE Semaphore Belgium
Chaussée de Bruxelles, 732A
B-1410 Waterloo
Belgium
T +32 (2) 387 42 59
F +32 (2) 387 42 75
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Interrupt handling documentation
From: Laurent Pinchart @ 2008-03-11 10:58 UTC (permalink / raw)
To: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 812 bytes --]
Hi everybody,
is there any documentation describing interrupt handling for the powerpc
architecture ? I'm writing a driver for a cascaded interrupt controller and
the only source of information I found was the code.
I'm particularly interested in information about irq hosts (allocation and
initialisation, especially the map and unmap callbacks) and irq chaining.
Different drivers seem to implement cascaded irqs differently (for instance
arch/powerpc/sysdev/uic.c uses setup_irq to register the cascaded irq
handler, while arch/powerpc/platforms/82xx/pq2ads-pci-pic.c uses
set_irq_chained_handler) so I'm a bit lost here.
Best regards,
--
Laurent Pinchart
CSE Semaphore Belgium
Chaussée de Bruxelles, 732A
B-1410 Waterloo
Belgium
T +32 (2) 387 42 59
F +32 (2) 387 42 75
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [RFC/PATCH] [POWER] mpc85xx_ds add DMA engine to the DT and parse it.
From: Sebastian Siewior @ 2008-03-11 10:39 UTC (permalink / raw)
To: linuxppc-embedded
The DT entry is copy / paste from the documentation.
Signed-off-by: Sebastian Siewior <bigeasy@linutronix.de>
---
arch/powerpc/boot/dts/mpc8544ds.dts | 41 ++++++++++++++++++++++++++++++
arch/powerpc/platforms/85xx/mpc85xx_ds.c | 13 +++++++++
2 files changed, 54 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/boot/dts/mpc8544ds.dts b/arch/powerpc/boot/dts/mpc8544ds.dts
index 688af9d..fdaf793 100644
--- a/arch/powerpc/boot/dts/mpc8544ds.dts
+++ b/arch/powerpc/boot/dts/mpc8544ds.dts
@@ -116,6 +116,47 @@
};
};
+ dma@21300 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8540-dma", "fsl,eloplus-dma";
+ reg = <21300 4>;
+ ranges = <0 21100 200>;
+ cell-index = <0>;
+ dma-channel@0 {
+ compatible = "fsl,mpc8540-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0 80>;
+ cell-index = <0>;
+ interrupt-parent = <&mpic>;
+ interrupts = <14 2>;
+ };
+ dma-channel@80 {
+ compatible = "fsl,mpc8540-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <80 80>;
+ cell-index = <1>;
+ interrupt-parent = <&mpic>;
+ interrupts = <15 2>;
+ };
+ dma-channel@100 {
+ compatible = "fsl,mpc8540-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <100 80>;
+ cell-index = <2>;
+ interrupt-parent = <&mpic>;
+ interrupts = <16 2>;
+ };
+ dma-channel@180 {
+ compatible = "fsl,mpc8540-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <180 80>;
+ cell-index = <3>;
+ interrupt-parent = <&mpic>;
+ interrupts = <17 2>;
+ };
+ };
+
enet0: ethernet@24000 {
cell-index = <0>;
device_type = "network";
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
index bdb3d0b..b9a3094 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
@@ -19,6 +19,7 @@
#include <linux/delay.h>
#include <linux/seq_file.h>
#include <linux/interrupt.h>
+#include <linux/of_platform.h>
#include <asm/system.h>
#include <asm/time.h>
@@ -183,6 +184,18 @@ static int __init mpc8544_ds_probe(void)
}
}
+static struct of_device_id mpc85xxds_ids[] = {
+ { .type = "soc", },
+ { .compatible = "soc", },
+ {},
+};
+
+static int __init mpc85xxds_publish_devices(void)
+{
+ return of_platform_bus_probe(NULL, mpc85xxds_ids, NULL);
+}
+machine_device_initcall(mpc8544_ds, mpc85xxds_publish_devices);
+
/*
* Called very early, device-tree isn't unflattened
*/
--
1.5.4.3
^ permalink raw reply related
* Re: ARCH=ppc -> ARCH=powerpc : help needed for dts file
From: Philippe De Muyter @ 2008-03-11 11:46 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Scott Wood, linuxppc-dev
In-Reply-To: <20080311003249.GG11559@localhost.localdomain>
Hi David,
On Tue, Mar 11, 2008 at 11:32:49AM +1100, David Gibson wrote:
> On Sun, Mar 09, 2008 at 11:31:09PM +0100, Philippe De Muyter wrote:
> > Hi Ben,
> >
> > I now have a working linux on my mpc8540 based board, with support for
> > the compactflash disk and the i2c rtc.
> >
> > The network tough, does not work yet. altough the the integrated ethernet
> > controller (FEC) seems to be recognized. Could it be a problem with the phy ?
> > I notice that I do not have an entry for gfar_interrupt in /proc/interrupts
> > on my ethernet-missing linux, while I have one ont the working arch/ppc linux ?
> > Do I need to give the phy type in the dts file, and how ?
> >
> > I would also like to know if it is possible to still get in linux the mac
> > address known by uboot when using a dts file, and how ?
>
> This chiefly depends on whether you're using an old u-boot that
> doesn't know about the device tree, or a new u-boot which itself
> supplies a device tree to the kernel.
>
> If the old u-boot, you'll need to write a bootwrapper for your
> platform which reads the bd_t and pokes the right mac addresses into
> the device tree.
>
> If the new u-boot, u-boot itself should put the address into the
> device tree. If it's not, why it's not is a u-boot question rather
> than a device tree question.
OK :(
Now back to the first an bigger problem :
currently, I have an "old" U-boot and I have written myself a dts file.
Problem is : ethernet does not work, but that's not a mac-address problem,
but something else that I do not understand yet. The symptom is I get
ip route add default via 192.168.85.33 dev eth0
RTNETLINK answers: Network is unreachable
I surmise this is because my eth0 does not become up, and I surmise
again this is because there is no driver selected to drive the phy.
In my arch/ppc setup this was automagically handled by fixed@100:1 IIRC
Is there something I can put in my dts file to activate a driver for my phy ?
Best regards
Philippe
^ permalink raw reply
* Interrupt routing ARCH=ppc
From: Suresh Chandra Mannava @ 2008-03-11 12:54 UTC (permalink / raw)
To: linuxppc-dev, linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 1684 bytes --]
Hi All,
I am working on porting Linux 2.6.16.60 on PowerPC based board with Tsi109
system controller.
Our platform support is defined in arch/ppc
Here is our hardware interrupt routing
Tsi109 PCI BUS
(BUS 0)
|
|
V
VME controller (BUS 0 IDSEL 16) IRQ 36
PMC Slot (BUS 0 IDSEL 17) IRQ 37
PCI-PCI Bridge (BUS 0 IDSEL 18) No IRQ required
|
(BUS 1)|
|-------> PMC Slot (BUS 1 IDSEL 19) IRQ 38
USB Contr(BUS 1 IDSEL 20) IRQ 39
I faced a problem at map_irq. Due to pci_swizzle, PCI probe is always
returning p2p bridge IDSEL for all device on BUS 1.
In our case, we routed independent interrupt lines for the devices on BUS 1.
I made a quick workaround by assigning IRQ's based on dev->devfn.
Is there any standard way of assigning independent interrupts for the
devices connected below P2P bridge?
I am facing problem with on-board USB controller. Even though
/proc/interrupts shows correct assignment. USB is always returning the
following message
usb 2-1: new low speed USB device using ohci_hcd and address 2
ohci_hcd 0000:01:04.0: Unlink after no-IRQ? Controller is probably using
the wrong IRQ
If the interrupts are not assigned properly, how the above message pop-up
soon after inserting USB device?
Here is the proc entry
# cat /proc/interrupts
CPU0
12: 105 tsi108_pic Level serial
38: 4270 tsi108_PCI_int Level eth0
39: 1 tsi108_PCI_int Level ehci_hcd:usb1, ohci_hcd:usb2,
ohci_hcd :usb3
Whereas USB PMC on BUS 0 works fine.
I request you to provide some pointers on the same.
Thanks a lot,
Suresh
[-- Attachment #2: Type: text/html, Size: 2621 bytes --]
^ permalink raw reply
* Re: [PATCH] pasemi_dma: Driver for PA Semi PWRficient on-chip DMA engine
From: Olof Johansson @ 2008-03-11 14:25 UTC (permalink / raw)
To: Andrew Morton
Cc: hskinnemoen, shannon.nelson, linux-kernel, linuxppc-dev,
pasemi-linux, dan.j.williams
In-Reply-To: <20080311000619.ba39311f.akpm@linux-foundation.org>
On Tue, Mar 11, 2008 at 12:06:19AM -0700, Andrew Morton wrote:
> On Thu, 6 Mar 2008 17:39:00 -0600 Olof Johansson <olof@lixom.net> wrote:
>
> > pasemi_dma: Driver for PA Semi PWRficient on-chip DMA engine
> >
> > First cut at a dma copy offload driver for PA Semi PWRficient. It uses the
> > platform-specific functions to allocate channels, etc.
>
> Applied this on Paul's latest and powerpc allmodconfig goes boom.
It's dependent on my latest pull request of pasemi.git for-2.6.26 that
Paul hasn't pulled/pushed yet.
> drivers/dma/pasemi_dma.c: In function `pasemi_dma_alloc_chan_resources':
> drivers/dma/pasemi_dma.c:152: error: `PAS_DMA_TXCHAN_CFG_TY_COPY' undeclared (first use in this function)
> drivers/dma/pasemi_dma.c:152: error: (Each undeclared identifier is reported only once
> drivers/dma/pasemi_dma.c:152: error: for each function it appears in.)
> drivers/dma/pasemi_dma.c:154: error: `PAS_DMA_TXCHAN_CFG_LPDQ' undeclared (first use in this function)
> drivers/dma/pasemi_dma.c:155: error: `PAS_DMA_TXCHAN_CFG_LPSQ' undeclared (first use in this function)
> drivers/dma/pasemi_dma.c: In function `pasemi_dma_probe':
> drivers/dma/pasemi_dma.c:394: error: structure has no member named `device_dependency_added'
.. and that one is caused by recent changes in async_tx.git. I was
waiting on other review comments from the DMA maintainers before
resubmitting; timer has expired though and I'll do it anyway today.
> Also this driver from git-md-accel is pretty sick:
>
>
> drivers/dma/fsldma.c:439: warning: comparison of distinct pointer types lacks a cast
> drivers/dma/fsldma.c: In function `fsl_chan_xfer_ld_queue':
> drivers/dma/fsldma.c:584: warning: long long unsigned int format, dma_addr_t arg (arg 4)
> drivers/dma/fsldma.c: In function `fsl_dma_chan_do_interrupt':
> drivers/dma/fsldma.c:661: warning: unsigned int format, different type arg (arg 5)
> drivers/dma/fsldma.c:677: warning: long long unsigned int format, dma_addr_t arg (arg 4)
> drivers/dma/fsldma.c:677: warning: long long unsigned int format, dma_addr_t arg (arg 5)
> drivers/dma/fsldma.c:694: warning: unsigned int format, different type arg (arg 4)
> drivers/dma/fsldma.c: In function `fsl_dma_self_test':
> drivers/dma/fsldma.c:833: warning: int format, different type arg (arg 5)
> drivers/dma/fsldma.c: In function `of_fsl_dma_probe':
> drivers/dma/fsldma.c:1003: warning: unsigned int format, different type arg (arg 5)
> drivers/dma/fsldma.c: At top level:
> drivers/dma/fsldma.c:723: warning: 'fsl_dma_callback_test' defined but not used
Yeah, Zhang Wei posted a patch for that on lkml yesterday.
-Olof
^ permalink raw reply
* Help needed to describe a custom bus in the device tree
From: Laurent Pinchart @ 2008-03-11 14:27 UTC (permalink / raw)
To: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 4898 bytes --]
Hi everybody,
the migration process from ARCH=ppc to ARCH=powerpc is easier than I thought
in some parts, but a few devices are still giving me headaches. This should
hopefully be one of my last major requests for help (I'm sure most of you
will be happy to see traffic on this list going down when I'll be done :-))
I'm having trouble describing a custom bus named MS bus (completely unrelated
to a well-known software company) in the device tree. The hardware is
MPC8248-based and has the following hardware topology.
MPC8248 <-- localbus --> FPGA <-- ms bus --> Custom peripherals
The bus interrupt controller, serial access (SPI) controller and status
registers are accessed through memory-mapped registers in the FPGA. Parallel
access to the MS bus is handled transparently by the FPGA which handles
address mapping.
The FPGA is mapped on the locabus at address 0xf4000000. Bus control registers
are at 0xf4002000 - 0xf4003000. The parallel bus memory window on the
localbus is located at 0xf5000000.
My current dts draft describes that topology as follows (unrelated devices on
the local bus such as flash memory are removed for clarity).
localbus@f0010100 {
compatible = "fsl,pq2-localbus";
#address-cells = <2>;
#size-cells = <1>;
reg = <f0010100 40>;
ranges = <0 0 40000000 01000000
2 0 f2000000 00100000
3 0 f3000000 00100000
4 0 f4000000 00100000
5 0 f5000000 00100000>;
fpga@4,0 {
#address-cells = <1>;
#size-cells = <1>;
ranges = <4 0 0 00010000>;
msbus-arbitrer@2000 {
compatible = "tbox,cp11-msbus-arbitrer";
reg = <2000 4>;
};
msbus_pic: interrupt-controller@2100 {
compatible = "tbox,cp11-msbus-pic";
reg = <2100 8>;
interrupts = <17 2>;
interrupt-parent = <&cpm_pic>;
#interrupt-cells = <1>;
interrupt-controller;
};
msbus-spi@2200 {
compatible = "tbox,cp11-msbus-spi";
reg = <2200 100>;
interrupts = <18 8>;
interrupt-parent = <&cpm_pic>;
};
sdhc@5000 {
compatible = "tbox,sdhci";
reg = <5000 1000>;
interrupts = <16 8>;
interrupt-parent = <&cpm_pic>;
};
};
msbus@5,0 {
compatible = "tbox,cp11-msbus";
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <1>;
reg = <5 0 0 00000400>;
interrupt-parent = <&msbus_pic>;
};
};
The device tree reflects the physical topology but makes driver access to the
bus quite complex. An OF platform device driver matching on compatible
= "tbox,cp11-msbus" will not have the bus FPGA registers described in its
device node.
Having a look at the various device trees included in the kernel sources, it
seems platforms with a PCI bus experience a similar problem. To solve it the
PCI bus node address and registers describe the configuration registers, and
the memory window to access PCI devices is described by the ranges property.
Applying that to my custom bus would lead to the following tree.
localbus@f0010100 {
compatible = "fsl,pq2-localbus";
#address-cells = <2>;
#size-cells = <1>;
reg = <f0010100 40>;
ranges = <0 0 40000000 01000000
2 0 f2000000 00100000
3 0 f3000000 00100000
4 0 f4000000 00100000
4 1 f4002000 00000100
5 0 f5000000 00100000>;
fpga@4,0 {
#address-cells = <1>;
#size-cells = <1>;
ranges = <4 0 0 00010000>;
msbus_pic: interrupt-controller@2100 {
compatible = "tbox,cp11-msbus-pic";
reg = <2100 8>;
interrupts = <17 2>;
interrupt-parent = <&cpm_pic>;
#interrupt-cells = <1>;
interrupt-controller;
};
msbus-spi@2200 {
compatible = "tbox,cp11-msbus-spi";
reg = <2200 100>;
interrupts = <18 8>;
interrupt-parent = <&cpm_pic>;
};
sdhc@5000 {
compatible = "tbox,sdhci";
reg = <5000 1000>;
interrupts = <16 8>;
interrupt-parent = <&cpm_pic>;
};
};
msbus@4,1 {
compatible = "tbox,cp11-msbus";
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <1>;
reg = <4 1 4>;
interrupt-parent = <&msbus_pic>;
ranges = <5 0 0 00000400>;
};
};
Is this correct ? Is that the best way to describe my custom bus in the device
tree ? How would the relationships between the bus and its PIC and SPI
controller be handled in the drivers ? I also don't understand how interrupt
mappings are supposed to be handled. PCI busses have two CPM interrupt lines,
one for the PCI PIC and one for the PCI bus, with the PCI bus having the CPM
PIC as its interrupt controller. My bus PIC uses a single interrupt line. Is
there some documentation explaining how PICs and interrupt mappings should be
described ?
Thanks in advance for any help you can provide.
Best regards,
--
Laurent Pinchart
CSE Semaphore Belgium
Chaussée de Bruxelles, 732A
B-1410 Waterloo
Belgium
T +32 (2) 387 42 59
F +32 (2) 387 42 75
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* bootstrap loader + gzip 1.3.5 --> huge image!?
From: Robert Zach @ 2008-03-11 14:37 UTC (permalink / raw)
To: linuxppc-embedded
hi list!
I am using the xilinx git tree with the included bootstrap loader.
Everthing works fine when i use binutils-2.16.1-gcc-3.4.6-uClibc-0.9.29.
But when useing binutils-2.18.50-gcc-4.2.0-uClibc-0.9.29 (generated
with buildroot) i get the following problem:
At the end of the kernel build process the vmlinux image gets compressed
(for the bootstrap loader).
something like:
gzip -f -9 < arch/ppc/boot/images/vmlinux.bin >
arch/ppc/boot/images/vmlinux.gz.$$
when i compiled the kernel with binutils-2.16.1-gcc-3.4.6-uClibc-0.9.29
the resulting image size is smaller then the original and everything
works (the bootstrap loader uncompresses, the kernel boots, ..)
But when using the binutils-2.18.50-gcc-4.2.0-uClibc-0.9.29
cross-toolchain i get the following:
du arch/ppc/boot/images/vmlinux.bin
1264 arch/ppc/boot/images/vmlinux.bin
gzip -f -9 < arch/ppc/boot/images/vmlinux.bin >
arch/ppc/boot/images/vmlinux.gz.$$
du arch/ppc/boot/images/vmlinux.gz.$$
3640 arch/ppc/boot/images/vmlinux.gz
The resulting huge zImage.elf file does not work (the bootstraploader
stops somewhere early).
Its the same for all other toolchains i tryed using binutils > 2.16.
what does gzip do?
I use the following version
gzip --version
gzip 1.3.5
(2002-09-30)
Copyright 2002 Free Software Foundation
Copyright 1992-1993 Jean-loup Gailly
Does anybody know this problem?
any suggestions for a solution.
thanks in advanced!
greets!
robert
^ permalink raw reply
* RE: OF compatible MTD platform RAM driver ?
From: Rune Torgersen @ 2008-03-11 15:00 UTC (permalink / raw)
To: David Gibson; +Cc: linuxppc-dev, linux-mtd, ben
In-Reply-To: <20080311004545.GI11559@localhost.localdomain>
David Gibson wrote:
> On Mon, Mar 10, 2008 at 12:00:22PM -0500, Rune Torgersen wrote:
>> We ran ito the same issue.
>> We did option 3, as it was efinetly the easiest,
>=20
> I think this is the best option in principle.
>=20
>> here is the sram entry in our dts:
>=20
> Except that your implementation of it is not good.
>=20
> You're relying on the old obsolete flash binding with the "probe-type"
> field. The solution should be adapted to the new approach which uses
> values in the "compatible" field to indicate various sorts of flash
> device.
Yea, I know. But it was the easiest way of doing it at the time we did
our port....
In a timecrunch, easier is sometimes better than correct. :)
^ permalink raw reply
* of_serial vs legacy serial support with powerpc arch on 405
From: John Linn @ 2008-03-11 15:04 UTC (permalink / raw)
To: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 671 bytes --]
I've searched and found some threads, but it's still not clear to me.
I'm working on 405 with powerpc and trying to get UART550 working.
I know that I need speed, freq, and reg-shift properties in the device
tree and I have found patches for of_serial.c.
I still don't understand when to use of_serial.c (SERIAL_OF_PLATFORM) vs
the legacy support for serial ports. Is there any docs that I'm not
finding that I should read?
I don't see a way to configure in the legacy support, but I'm using
SERIAL_OF and having problems. I don't see the console getting enabled
even though it found the serial port driver.
Thanks,
John
[-- Attachment #2: Type: text/html, Size: 8222 bytes --]
^ permalink raw reply
* RE: Add some documentation for the dts formta
From: Yoder Stuart @ 2008-03-11 15:34 UTC (permalink / raw)
To: David Gibson, Loeliger Jon; +Cc: linuxppc-dev
In-Reply-To: <20080310234714.GB11559@localhost.localdomain>
Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com>=20
> -----Original Message-----
> From: David Gibson [mailto:david@gibson.dropbear.id.au]=20
> Sent: Monday, March 10, 2008 6:47 PM
> To: Loeliger Jon
> Cc: Yoder Stuart; linuxppc-dev@ozlabs.org
> Subject: dtc: Add some documentation for the dts formta
>=20
> This patch adds a dts-format.txt in the Documentation directory, with
> an introduction to the dtc source format. Note that this
> documentation is also going into the upcoming ePAPR specification.
>=20
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
>=20
> ---
> Documentation/dts-format.txt | 110=20
> +++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 110 insertions(+)
>=20
> I wrote this documentation based on an earlier draft from Stuart
> Yoder. Stuart, can you please reply with a Signed-off-by line?
>=20
> Index: dtc/Documentation/dts-format.txt
> =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> --- /dev/null 1970-01-01 00:00:00.000000000 +0000
> +++ dtc/Documentation/dts-format.txt 2008-03-11=20
> 10:42:17.000000000 +1100
> @@ -0,0 +1,110 @@
> +Device Tree Source Format (version 1)
> =
+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> +
> +The Device Tree Source (DTS) format is a textual representation of a
> +device tree in a form that can be processed by dtc into a binary
> +device tree in the form expected by the kernel. The=20
> description below
> +is not a formal syntax definition of DTS, but describes the basic
> +constructs used to represent device trees.
> +
> +Node and property definitions
> +-----------------------------
> +
> +Device tree nodes are defined with a node name and unit address with
> +braces marking the start and end of the node definition. They may be
> +preceded by a label.
> +
> + [label:] node-name[@unit-address] {
> + [properties definitions]
> + [child nodes]
> + }
> +
> +Nodes may contain property definitions and/or child node
> +definitions. If both are present, properties must come before child
> +nodes.
> +
> +Property definitions are name value pairs in the form:
> + [label:] property-name =3D value;
> +except for properties with empty (zero length) value which have the
> +form:
> + [label:] property-name;
> +
> +Property values may be defined as an array of 32-bit integer=20
> cells, as
> +NUL-terminated strings, as bytestrings or a combination of these.
> +
> +* Arrays of cells are represented by angle brackets surrounding a
> + space separated list of C-style integers
> +
> + e.g. interrupts =3D <17 0xc>;
> +
> +* A 64-bit value is represented with two 32-bit cells.
> +
> + e.g. clock-frequency =3D <0x00000001 0x00000000>;
> +
> +* A NUL-terminated string value is represented using double quotes
> + (the property value is considered to include the terminating NUL
> + character).
> +
> + e.g. compatible =3D "simple-bus";
> +
> +* A bytestring is enclosed in square brackets [] with each byte
> + represented by two hexadecimal digits. Spaces between=20
> each byte are
> + optional.
> +
> + e.g. local-mac-address =3D [00 00 12 34 56 78]; or equivalently
> + local-mac-address =3D [000012345678];
> +
> +* Values may have several comma-separated components, which are
> + concatenated together.
> + e.g. compatible =3D "ns16550", "ns8250";
> + example =3D <0xf00f0000 19>, "a strange property format";
> +
> +* In a cell array a reference to another node will be=20
> expanded to that
> + node's phandle. References may by '&' followed by a node's label:
> + e.g. interrupt-parent =3D < &mpic >;
> + or they may be '&' followed by a node's full path in braces:
> + e.g. interrupt-parent =3D < &{/soc/interrupt-controller@40000} >;
> +
> +* Outside a cell array, a reference to another node will be expanded
> + to that node's full path.
> + e.g. ethernet0 =3D &EMAC0;
> +
> +* Labels may also appear before or after any component of a property
> + value, or between cells of a cell array, or between bytes of a
> + bytestring.
> + e.g. reg =3D reglabel: <0 sizelabel: 0x1000000>;
> + e.g. prop =3D [ab cd ef byte4: 00 ff fe];
> + e.g. str =3D start: "string value" end: ;
> +
> +
> +File layout
> +-----------
> +
> +Version 1 DTS files have the overall layout:
> + /dts-v1/;
> +
> + [memory reservations]
> +
> + / {
> + [property definitions]
> + [child nodes]
> + };
> +
> +* The "/dts-v1/;" must be present to identify the file as a version 1
> + DTS (dts files without this tag will be treated by dtc as being in
> + the obsolete "version 0", which uses a different format=20
> for integers
> + amongst other small but incompatible changes).
> +
> +* Memory reservations define an entry for the device tree blob's
> + memory reservation table. They have the form:
> + e.g. /memreserve/ <address> <length>;
> + Where <address> and <length> are 64-bit C-style integers.
> +
> +* The / { ... }; section defines the root node of the device tree.
> +
> +* C style (/* ... */) and C++ style (// ...) comments are supported.
> +
> +
> +
> + -- David Gibson <david@gibson.dropbear.id.au>
> + -- Yoder Stuart <stuart.yoder@freescale.com>
>=20
>=20
> --=20
> David Gibson | I'll have my music baroque,=20
> and my code
> david AT gibson.dropbear.id.au | minimalist, thank=20
> you. NOT _the_ _other_
> | _way_ _around_!
> http://www.ozlabs.org/~dgibson
>=20
^ permalink raw reply
* Re: bootstrap loader + gzip 1.3.5 --> huge image!?
From: rza1 @ 2008-03-11 15:45 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <47D6992B.6060208@so-logic.net>
I just recognized that gzip does his job right.
But objcopy of all binutils > 2.16.1 has problems during binary copy:
powerpc-linux-objcopy -O binary vmlinux arch/ppc/boot/images/vmlinux.bin
The vmlinux file does look good (what i can see with vi) but the
generated vmlinux.bin file is strange. Windows machines say that the
vmlinux.bin file is > then 3GByte, but linux says 1,5Mbyte. But, I can't
open it with vi...
Anywhay i think binutils > 2.16.1 has some problems with ppc.
Does anyone else use buildroot for ppc405 platform and solved the
problems with actual binutils versions?
cheers!
robert
Robert Zach wrote:
> hi list!
>
> I am using the xilinx git tree with the included bootstrap loader.
> Everthing works fine when i use binutils-2.16.1-gcc-3.4.6-uClibc-0.9.29.
>
> But when useing binutils-2.18.50-gcc-4.2.0-uClibc-0.9.29 (generated
> with buildroot) i get the following problem:
>
> At the end of the kernel build process the vmlinux image gets
> compressed (for the bootstrap loader).
> something like:
> gzip -f -9 < arch/ppc/boot/images/vmlinux.bin >
> arch/ppc/boot/images/vmlinux.gz.$$
> when i compiled the kernel with
> binutils-2.16.1-gcc-3.4.6-uClibc-0.9.29 the resulting image size is
> smaller then the original and everything works (the bootstrap loader
> uncompresses, the kernel boots, ..)
>
> But when using the binutils-2.18.50-gcc-4.2.0-uClibc-0.9.29
> cross-toolchain i get the following:
> du arch/ppc/boot/images/vmlinux.bin
> 1264 arch/ppc/boot/images/vmlinux.bin
> gzip -f -9 < arch/ppc/boot/images/vmlinux.bin >
> arch/ppc/boot/images/vmlinux.gz.$$
> du arch/ppc/boot/images/vmlinux.gz.$$
> 3640 arch/ppc/boot/images/vmlinux.gz
>
> The resulting huge zImage.elf file does not work (the bootstraploader
> stops somewhere early).
> Its the same for all other toolchains i tryed using binutils > 2.16.
>
> what does gzip do?
> I use the following version
> gzip --version
> gzip 1.3.5
> (2002-09-30)
> Copyright 2002 Free Software Foundation
> Copyright 1992-1993 Jean-loup Gailly
>
> Does anybody know this problem?
> any suggestions for a solution.
>
> thanks in advanced!
> greets!
> robert
>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
^ permalink raw reply
* Re: issue about CONFIG_PPC_MMU and CONFIG_SMP define
From: Becky Bruce @ 2008-03-11 15:53 UTC (permalink / raw)
To: jie han; +Cc: linuxppc-embedded@ozlabs.org
In-Reply-To: <604678.57629.qm@web15104.mail.cnb.yahoo.com>
On Mar 10, 2008, at 3:15 PM, jie han wrote:
> Hi guys,
>
> I want to simulate compile mutli-core using sequoia(IBM/AMCC 44x
> processor) source code under kernel arch/powerpc directory.I want
> to define CONFIG_SMP, I sould define CONFIG_STD_MMU at first,but
> AMCC 44x don't need to config CONFIG_STD_MMU.Is CONFIG_STD_MMU just
> for freescale chip? How can I do next? Thanks ahead for your help,
STD_MMU is for all powerpc cpus with a non-BookE MMU. That includes
all the 64-bit parts from IBM to date, pasemi's parts, and 32-bit
parts from IBM & Freescale like the 6xx, 7xx, 7xxx, e600 e300, etc.
You cannot set this for 44x, because it is a BookE part.
BTW, there's no real relationship between STD_MMU and SMP. It was
just a convenient way to restrict the SMP config option in the
kernel, since all the Linux configs that currently support SMP are
STD_MMU. We will have BookE configs in the future that do support
SMP, at which point arch/powerpc/platforms/Kconfig.cputype will be
changed to allow SMP to be set for those configs.
You can't enable SMP on 44x right now. It's not supported.
Cheers,
B
^ permalink raw reply
* [PATCH] Ported Xilinx GPIO driver to OpenFirmware.
From: Magnus Hjorth @ 2008-03-11 16:12 UTC (permalink / raw)
To: git; +Cc: linuxppc-embedded
From: Magnus Hjorth <mh@omnisys.se>
Added of_device structure and init code.=20
Basic functionality tested (LED:s on/off).
Added code to validate channel number in ioctl.
Signed-off-by: Magnus Hjorth <mh@omnisys.se>
---
Patch against Xilinx GIT tree (commit 7fb2b...)
Did this as a learning exercise. Hope it gets through Outlook in one =
piece :)
Cheers /Magnus
diff --git a/drivers/char/xilinx_gpio/adapter.c =
b/drivers/char/xilinx_gpio/adapter.c
index ecd2897..6fdf7aa 100644
--- a/drivers/char/xilinx_gpio/adapter.c
+++ b/drivers/char/xilinx_gpio/adapter.c
@@ -43,15 +43,22 @@
#include <asm/irq.h>
#include <linux/interrupt.h>
=20
+#ifdef CONFIG_OF
+// For open firmware.
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#endif
+
#define BUFSIZE 200
#define MIN(x,y) (x < y ? x : y)
=20
-
struct xgpio_instance {
struct list_head link;
unsigned long base_phys; /* GPIO base address - physical */
unsigned long remap_size;
- u32 device_id;
+ u32 device_id; /* Dev ID for platform devices, 0 for OF devices */
+ void *of_id; /* of_dev pointer for OF devices, NULL for plat devices =
*/
+ int is_dual;
wait_queue_head_t wait;
unsigned int head, tail, count;
__u64 buf[BUFSIZE]; /* 32xChan1, 32xChan2 */
@@ -125,8 +132,7 @@ static struct xgpio_instance *xgpio_getinst(unsigned =
int minor)
up_read(&inst_list_sem);
if (XGpio_IsReady(&inst->gpio)) {
return inst;
- }
- else {
+ } else {
return NULL;
}
}
@@ -147,6 +153,10 @@ static int xgpio_ioctl(struct inode *inode, struct =
file *file,
if (copy_from_user(&ioctl_data, (void *) arg, sizeof(ioctl_data)))
return -EFAULT;
=20
+ /* Validate channel number */
+ if (ioctl_data.chan !=3D 1 && (ioctl_data.chan !=3D 2 || =
!inst->is_dual))
+ return -EINVAL;
+
switch (cmd) {
case XGPIO_IN:
/*
@@ -216,6 +226,7 @@ static int xgpio_ioctl(struct inode *inode, struct =
file *file,
return -ENOIOCTLCMD;
=20
}
+
return 0;
}
=20
@@ -237,7 +248,6 @@ static unsigned int prev(unsigned int ptr)
return ptr;
}
=20
-
static ssize_t xgpio_read(struct file *file, char *buf,
size_t count, loff_t * ppos)
{
@@ -278,7 +288,6 @@ static ssize_t xgpio_read(struct file *file, char =
*buf,
return 0;
}
=20
-
static irqreturn_t xgpio_interrupt(int irq, void *dev_id)
{
struct xgpio_instance *inst =3D dev_id;
@@ -287,7 +296,6 @@ static irqreturn_t xgpio_interrupt(int irq, void =
*dev_id)
inst->gpio.IsDual ? XIo_In32(inst->gpio.BaseAddress + 0x08) : 0;
__u32 int_status =3D XIo_In32(inst->gpio.BaseAddress + 0x120);
=20
-
if (inst->buf[prev(inst->tail)] !=3D
(((__u64) val_1) | ((__u64) (val_2) << 32)))
if (next(inst->tail) !=3D inst->head) {
@@ -303,7 +311,6 @@ static irqreturn_t xgpio_interrupt(int irq, void =
*dev_id)
return IRQ_HANDLED;
}
=20
-
/*
* We get to all of the GPIOs through one minor number. Here's the
* miscdevice that gets registered for that minor number.
@@ -335,45 +342,33 @@ char *names[] =3D {
=20
static int minor =3D XGPIO_MINOR;
=20
-static int xgpio_probe(struct device *dev)
+static int xgpio_probe_main(struct device *dev, int dev_id, void =
*of_dev_id,
+ int is_dual,
+ struct resource *irq_res, struct resource *regs_res)
{
XGpio_Config xgpio_config;
struct xgpio_instance *xgpio_inst;
struct miscdevice *miscdev =3D 0;
- struct platform_device *pdev =3D to_platform_device(dev);
- struct resource *irq_res, *regs_res;
void *v_addr;
int retval;
=20
- if (!dev)
- return -EINVAL;
-
memset(&xgpio_config, 0, sizeof(XGpio_Config));
xgpio_inst =3D kmalloc(sizeof(struct xgpio_instance), GFP_KERNEL);
if (!xgpio_inst) {
printk(KERN_ERR
"%s #%d: Couldn't allocate device private record\n",
- miscdev->name, pdev->id);
+ miscdev->name, dev_id);
return -ENOMEM;
}
memset(xgpio_inst, 0, sizeof(struct xgpio_instance));
=20
- /* Map the control registers in */
- regs_res =3D platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!regs_res || (regs_res->end - regs_res->start + 1 < 8)) {
- printk(KERN_ERR "%s #%d: Couldn't get registers resource\n",
- miscdev->name, pdev->id);
- retval =3D -EFAULT;
- goto failed1;
- }
-
xgpio_inst->remap_size =3D regs_res->end - regs_res->start + 1;
if (!request_mem_region(regs_res->start, xgpio_inst->remap_size,
DRIVER_NAME)) {
printk(KERN_ERR "Couldn't lock memory region at 0x%08lX\n",
(unsigned long) regs_res->start);
retval =3D -EBUSY;
- goto failed2;
+ goto failed1;
}
=20
v_addr =3D ioremap(regs_res->start, xgpio_inst->remap_size);
@@ -381,21 +376,22 @@ static int xgpio_probe(struct device *dev)
printk(KERN_ERR "Couldn't ioremap memory at 0x%08lX\n",
(unsigned long) regs_res->start);
retval =3D -EFAULT;
- goto failed3;
+ goto failed2;
}
=20
xgpio_inst->base_phys =3D regs_res->start;
/* The 1st GPIO channel uses */
- xgpio_inst->device_id =3D pdev->id;
- xgpio_config.DeviceId =3D pdev->id;
- xgpio_config.IsDual =3D
- ((unsigned) (dev->platform_data) & XGPIO_IS_DUAL) ? 1 : 0;
+ xgpio_inst->device_id =3D dev_id;
+ xgpio_inst->of_id =3D of_dev_id;
+ xgpio_inst->is_dual =3D is_dual ? 1 : 0;
+ xgpio_config.DeviceId =3D dev_id;
+ xgpio_config.IsDual =3D is_dual ? 1 : 0;
=20
/* Tell the Xilinx code to bring this GPIO interface up. */
if (XGpio_CfgInitialize(&xgpio_inst->gpio, &xgpio_config,
(u32) v_addr) !=3D XST_SUCCESS) {
printk(KERN_ERR "%s #%d: Could not initialize instance.\n",
- miscdev->name, pdev->id);
+ miscdev->name, dev_id);
retval =3D -ENODEV;
goto failed3;
}
@@ -407,7 +403,7 @@ static int xgpio_probe(struct device *dev)
if (!miscdev) {
printk(KERN_ERR
"%s #%d: Couldn't allocate device private record\n",
- "xgpio", pdev->id);
+ "xgpio", dev_id);
return -ENOMEM;
}
=20
@@ -419,7 +415,7 @@ static int xgpio_probe(struct device *dev)
if (retval !=3D 0) {
up_write(&inst_list_sem);
printk(KERN_ERR "%s #%d: Could not register miscdev.\n",
- miscdev->name, pdev->id);
+ miscdev->name, dev_id);
goto failed3;
}
=20
@@ -427,7 +423,6 @@ static int xgpio_probe(struct device *dev)
=20
minor++;
=20
- irq_res =3D platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (irq_res) {
if (request_irq(irq_res->start,
xgpio_interrupt, 0, "XGPIO", xgpio_inst))
@@ -471,24 +466,45 @@ static int xgpio_probe(struct device *dev)
return retval;
}
=20
-static int xgpio_remove(struct device *dev)
+static int xgpio_probe(struct device *dev)
{
- struct list_head *entry;
- struct xgpio_instance *xgpio_inst =3D NULL;
struct platform_device *pdev =3D to_platform_device(dev);
+ struct resource *irq_res, *regs_res;
+ int is_dual;
=20
if (!dev)
return -EINVAL;
=20
+ /* Map the control registers in */
+ regs_res =3D platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!regs_res || (regs_res->end - regs_res->start + 1 < 8)) {
+ dev_err(dev, "couldn't get registers resource\n");
+ return -EFAULT;
+ }
+
+ irq_res =3D platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+ is_dual =3D ((unsigned)(dev->platform_data) & XGPIO_IS_DUAL);
+
+ return xgpio_probe_main(dev, pdev->id, NULL, is_dual, irq_res,
+ regs_res);
+}
+
+static int xgpio_remove_main(struct device *dev, int dev_id, void =
*of_dev_id)
+{
+ struct list_head *entry;
+ struct xgpio_instance *xgpio_inst =3D NULL;
+ struct platform_device *pdev =3D to_platform_device(dev);
+
/* Set xgpio_inst based on pdev->id match */
=20
down_read(&inst_list_sem);
list_for_each(entry, &inst_list) {
xgpio_inst =3D list_entry(entry, struct xgpio_instance, link);
- if (pdev->id =3D=3D xgpio_inst->device_id) {
+ if (pdev->id =3D=3D xgpio_inst->device_id &&
+ of_dev_id =3D=3D xgpio_inst->of_id) {
break;
- }
- else {
+ } else {
xgpio_inst =3D NULL;
}
}
@@ -515,6 +531,16 @@ static int xgpio_remove(struct device *dev)
return 0; /* success */
}
=20
+static int xgpio_remove(struct device *dev)
+{
+ struct platform_device *pdev =3D to_platform_device(dev);
+
+ if (!dev)
+ return -EINVAL;
+
+ return xgpio_remove_main(dev, pdev->id, NULL);
+}
+
static struct device_driver xgpio_driver =3D {
.name =3D DRIVER_NAME,
.bus =3D &platform_bus_type,
@@ -523,13 +549,77 @@ static struct device_driver xgpio_driver =3D {
.remove =3D xgpio_remove
};
=20
+#ifdef CONFIG_OF
+
+static int __devinit xgpio_of_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ struct resource r_irq_struct, r_mem_struct;
+ struct resource *r_irq;
+ int rc;
+ int l;
+ const u32 *p;
+ int is_dual;
+
+ rc =3D of_address_to_resource(ofdev->node, 0, &r_mem_struct);
+ if (rc) {
+ dev_warn(&ofdev->dev, "invalid address\n");
+ return rc;
+ }
+
+ rc =3D of_irq_to_resource(ofdev->node, 0, &r_irq_struct);
+ if (rc =3D=3D NO_IRQ)
+ r_irq =3D NULL;
+ else
+ r_irq =3D &r_irq_struct;
+
+ p =3D of_get_property(ofdev->node, "xlnx,is-dual", &l);
+ if (p =3D=3D NULL || l !=3D sizeof(*p)) {
+ dev_warn(&ofdev->dev, "Property not found: xlnx,is-dual\n");
+ is_dual =3D 0;
+ } else
+ is_dual =3D *p;
+
+ return xgpio_probe_main(&ofdev->dev, 0, ofdev, is_dual, r_irq,
+ &r_mem_struct);
+}
+
+static int __devexit xgpio_of_remove(struct of_device *ofdev)
+{
+ if (!ofdev)
+ return -EINVAL;
+
+ return xgpio_remove_main(&ofdev->dev, 0, ofdev);
+}
+
+static struct of_device_id xgpio_of_match[] =3D {
+ {.compatible =3D "xlnx,xps-gpio-1.00.a"},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, xgpio_of_match);
+
+static struct of_platform_driver xgpio_of_driver =3D {
+ .name =3D DRIVER_NAME,
+ .match_table =3D xgpio_of_match,
+ .probe =3D xgpio_of_probe,
+ .remove =3D __devexit_p(xgpio_of_remove),
+};
+
+#endif
+
static int __init xgpio_init(void)
{
+ int s;
/*
* No kernel boot options used,
* so we just need to register the driver
*/
- return driver_register(&xgpio_driver);
+ s =3D driver_register(&xgpio_driver);
+#ifdef CONFIG_OF
+ s |=3D of_register_platform_driver(&xgpio_of_driver);
+#endif
+ return s;
}
=20
static void __exit xgpio_cleanup(void)
--=20
1.5.4.4
--
Magnus Hjorth, M.Sc.
Omnisys Instruments AB
Gruvgatan 8
SE-421 30 V=E4stra Fr=F6lunda, SWEDEN
Phone: +46 31 734 34 09
Fax: +46 31 734 34 29
http://www.omnisys.se
^ permalink raw reply related
* Re: [PATCH 3/8] pseries: phyp dump: use sysfs to release reserved mem
From: Dale Farnsworth @ 2008-03-11 16:44 UTC (permalink / raw)
To: Linuxppc-dev
In-Reply-To: <18390.9137.626123.104628@cargo.ozlabs.ibm.com>
Paul wrote:
> Manish Ahuja writes:
> > + dump_header = of_get_property(rtas, "ibm,kernel-dump",
> > + &header_len);
>
> This is a somewhat weird-looking way of coping with too-long lines.
Yes, but not too surprising, since it precisely follows the recommendation
(and the example) in Chapter 2 of Documentation/CodingStyle. :)
-Dale
^ permalink raw reply
* Re: [PATCH] pasemi_dma: Driver for PA Semi PWRficient on-chip DMAengine
From: Dan Williams @ 2008-03-11 17:04 UTC (permalink / raw)
To: Olof Johansson
Cc: linuxppc-dev, pasemi-linux, Nelson, Shannon, linux-kernel,
hskinnemoen
In-Reply-To: <20080306233900.GA3969@lixom.net>
On Thu, 2008-03-06 at 16:39 -0700, Olof Johansson wrote:
> pasemi_dma: Driver for PA Semi PWRficient on-chip DMA engine
>
> First cut at a dma copy offload driver for PA Semi PWRficient. It uses the
> platform-specific functions to allocate channels, etc.
>
> Signed-off-by: Olof Johansson <olof@lixom.net>
>
>
> ---
>
> This has some dependencies on other patches currently queued up in the
> powerpc git trees for 2.6.26. I'd appreciate reviews and acked-bys, but
> it might be easiest to just merge it up the powerpc path due to the
> dependencies.
>
Apologies for not getting to this sooner.
I notice that the driver does not handle callbacks in its descriptor
cleanup path. This could be ok if your intent is only to support the
net_dma style polled operations, but this will not work for the
raid-offload async_tx case. I think the solution is for async_tx to
ignore channels without the DMA_INTERRUPT capability.
> +static void pasemi_dma_clean(struct pasemi_dma_chan *chan)
> +{
> + int old, new, i;
> + unsigned long flags;
> + struct pasemi_dma_desc *desc;
> + spin_lock_irqsave(&chan->desc_lock, flags);
Is spin_lock_bh() insufficient here?
...that's all that jumps out at the moment.
Regards,
Dan
^ permalink raw reply
* [PATCH 1/2] [POWERPC] fsl_soc: add support for "fsl, soc" compatible matching
From: Anton Vorontsov @ 2008-03-11 17:10 UTC (permalink / raw)
To: linuxppc-dev
As we've seen, fsl,immr isn't good name for the generic purposes,
because some SOCs use ccsr term. So, for generic matching, "fsl,soc"
is used, whereas "fsl,immr" and "fsl,ccsr" is used for more specific
matching.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
Documentation/powerpc/booting-without-of.txt | 20 +++++------
arch/powerpc/sysdev/fsl_soc.c | 51 +++++++++++++++-----------
2 files changed, 39 insertions(+), 32 deletions(-)
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index 7b4e8a7..be41a5c 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -32,7 +32,7 @@ Table of Contents
c) The /cpus/* nodes
d) the /memory node(s)
e) The /chosen node
- f) the /soc<SOCname> node
+ f) the /soc node
IV - "dtc", the device tree compiler
@@ -961,20 +961,17 @@ compatibility.
under /chosen called interrupt-controller which had a phandle value
that pointed to the main interrupt controller)
- f) the /soc<SOCname> node
+ f) the /soc node
This node is used to represent a system-on-a-chip (SOC) and must be
present if the processor is a SOC. The top-level soc node contains
- information that is global to all devices on the SOC. The node name
- should contain a unit address for the SOC, which is the base address
- of the memory-mapped register set for the SOC. The name of an soc
- node should start with "soc", and the remainder of the name should
- represent the part number for the soc. For example, the MPC8540's
- soc node would be called "soc8540".
+ information that is global to all devices on the SOC. The name of an
+ soc node should be "soc".
Required properties:
- - device_type : Should be "soc"
+ - compatible : Should be "<cpu>-<immr or ccsr>", "fsl,<immr or ccsr>",
+ "fsl,soc", "simple-bus".
- ranges : Should be defined as specified in 1) to describe the
translation of SOC addresses for memory mapped SOC registers.
- bus-frequency: Contains the bus frequency for the SOC node.
@@ -2913,11 +2910,12 @@ Note that the #address-cells and #size-cells for the SoC node
in this example have been explicitly listed; these are likely
not necessary as they are usually the same as the root node.
- soc8540@e0000000 {
+ soc@e0000000 {
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <2>;
- device_type = "soc";
+ compatible = "fsl,mpc8540-ccsr", "fsl,ccsr", "fsl,soc",
+ "simple-bus";
ranges = <00000000 e0000000 00100000>
reg = <e0000000 00003000>;
bus-frequency = <0>;
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 2c5388c..7ad9bce 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -48,27 +48,31 @@ static phys_addr_t immrbase = -1;
phys_addr_t get_immrbase(void)
{
struct device_node *soc;
+ int size;
+ u32 naddr;
+ const u32 *prop;
if (immrbase != -1)
return immrbase;
- soc = of_find_node_by_type(NULL, "soc");
- if (soc) {
- int size;
- u32 naddr;
- const u32 *prop = of_get_property(soc, "#address-cells", &size);
+ soc = of_find_compatible_node(NULL, NULL, "fsl,soc");
+ if (!soc) {
+ soc = of_find_node_by_type(NULL, "soc");
+ if (!soc)
+ return immrbase;
+ }
- if (prop && size == 4)
- naddr = *prop;
- else
- naddr = 2;
+ prop = of_get_property(soc, "#address-cells", &size);
+ if (prop && size == 4)
+ naddr = *prop;
+ else
+ naddr = 2;
- prop = of_get_property(soc, "ranges", &size);
- if (prop)
- immrbase = of_translate_address(soc, prop + naddr);
+ prop = of_get_property(soc, "ranges", &size);
+ if (prop)
+ immrbase = of_translate_address(soc, prop + naddr);
- of_node_put(soc);
- }
+ of_node_put(soc);
return immrbase;
}
@@ -528,11 +532,13 @@ static int __init mpc83xx_wdt_init(void)
goto nodev;
}
- soc = of_find_node_by_type(NULL, "soc");
-
+ soc = of_find_compatible_node(NULL, NULL, "fsl,soc");
if (!soc) {
- ret = -ENODEV;
- goto nosoc;
+ soc = of_find_node_by_type(NULL, "soc");
+ if (!soc) {
+ ret = -ENODEV;
+ goto nosoc;
+ }
}
freq = of_get_property(soc, "bus-frequency", NULL);
@@ -1375,9 +1381,12 @@ int __init fsl_spi_init(struct spi_board_info *board_infos,
const u32 *freq;
int size;
- np = of_find_node_by_type(NULL, "soc");
- if (!np)
- return -ENODEV;
+ np = of_find_compatible_node(NULL, NULL, "fsl,soc");
+ if (!np) {
+ np = of_find_node_by_type(NULL, "soc");
+ if (!np)
+ return -ENODEV;
+ }
freq = of_get_property(np, "clock-frequency", &size);
if (!freq || size != sizeof(*freq) || *freq == 0) {
--
1.5.2.2
^ permalink raw reply related
* [PATCH 2/2] [POWERPC] UCC nodes cleanup
From: Anton Vorontsov @ 2008-03-11 17:10 UTC (permalink / raw)
To: linuxppc-dev
- get rid of `model = "UCC"' in the ucc nodes
It isn't used anywhere, so remove it. If we'll ever need something
like this, we'll use compatible property instead.
- replace cell-index and device-id properties by fsl,ucc.
Drivers are modified for backward compatibility's sake.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
Documentation/powerpc/booting-without-of.txt | 6 ++----
arch/powerpc/boot/dts/mpc832x_mds.dts | 11 +++--------
arch/powerpc/boot/dts/mpc832x_rdb.dts | 8 ++------
arch/powerpc/boot/dts/mpc836x_mds.dts | 8 ++------
arch/powerpc/boot/dts/mpc8568mds.dts | 12 ++++--------
drivers/net/ucc_geth.c | 8 +++++++-
drivers/net/ucc_geth_mii.c | 11 ++++++++---
drivers/serial/ucc_uart.c | 16 ++++++++++++----
8 files changed, 40 insertions(+), 40 deletions(-)
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index be41a5c..8ae57f2 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -1619,8 +1619,7 @@ platforms are moved over to use the flattened-device-tree model.
- device_type : should be "network", "hldc", "uart", "transparent"
"bisync", "atm", or "serial".
- compatible : could be "ucc_geth" or "fsl_atm" and so on.
- - model : should be "UCC".
- - device-id : the ucc number(1-8), corresponding to UCCx in UM.
+ - fsl,ucc : the ucc number(1-8), corresponding to UCCx in UM.
- reg : Offset and length of the register set for the device
- interrupts : <a b> where a is the interrupt number and b is a
field that represents an encoding of the sense and level
@@ -1677,8 +1676,7 @@ platforms are moved over to use the flattened-device-tree model.
ucc@2000 {
device_type = "network";
compatible = "ucc_geth";
- model = "UCC";
- device-id = <1>;
+ fsl,ucc = <1>;
reg = <2000 200>;
interrupts = <a0 0>;
interrupt-parent = <700>;
diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts
index 9bb4083..689e708 100644
--- a/arch/powerpc/boot/dts/mpc832x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc832x_mds.dts
@@ -255,9 +255,7 @@
enet0: ucc@2200 {
device_type = "network";
compatible = "ucc_geth";
- model = "UCC";
- cell-index = <3>;
- device-id = <3>;
+ fsl,ucc = <3>;
reg = <0x2200 0x200>;
interrupts = <34>;
interrupt-parent = <&qeic>;
@@ -271,9 +269,7 @@
enet1: ucc@3200 {
device_type = "network";
compatible = "ucc_geth";
- model = "UCC";
- cell-index = <4>;
- device-id = <4>;
+ fsl,ucc = <4>;
reg = <0x3200 0x200>;
interrupts = <35>;
interrupt-parent = <&qeic>;
@@ -287,8 +283,7 @@
ucc@2400 {
device_type = "serial";
compatible = "ucc_uart";
- model = "UCC";
- device-id = <5>; /* The UCC number, 1-7*/
+ fsl,ucc = <5>; /* The UCC number, 1-7*/
port-number = <0>; /* Which ttyQEx device */
soft-uart; /* We need Soft-UART */
reg = <0x2400 0x200>;
diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts
index 94f93d2..76e57ee 100644
--- a/arch/powerpc/boot/dts/mpc832x_rdb.dts
+++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts
@@ -208,9 +208,7 @@
enet0: ucc@3000 {
device_type = "network";
compatible = "ucc_geth";
- model = "UCC";
- cell-index = <2>;
- device-id = <2>;
+ fsl,ucc = <2>;
reg = <0x3000 0x200>;
interrupts = <33>;
interrupt-parent = <&qeic>;
@@ -224,9 +222,7 @@
enet1: ucc@2200 {
device_type = "network";
compatible = "ucc_geth";
- model = "UCC";
- cell-index = <3>;
- device-id = <3>;
+ fsl,ucc = <3>;
reg = <0x2200 0x200>;
interrupts = <34>;
interrupt-parent = <&qeic>;
diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts
index 55f03e8..e369749 100644
--- a/arch/powerpc/boot/dts/mpc836x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc836x_mds.dts
@@ -257,9 +257,7 @@
enet0: ucc@2000 {
device_type = "network";
compatible = "ucc_geth";
- model = "UCC";
- cell-index = <1>;
- device-id = <1>;
+ fsl,ucc = <1>;
reg = <0x2000 0x200>;
interrupts = <32>;
interrupt-parent = <&qeic>;
@@ -274,9 +272,7 @@
enet1: ucc@3000 {
device_type = "network";
compatible = "ucc_geth";
- model = "UCC";
- cell-index = <2>;
- device-id = <2>;
+ fsl,ucc = <2>;
reg = <0x3000 0x200>;
interrupts = <33>;
interrupt-parent = <&qeic>;
diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts
index 97bc048..884fe45 100644
--- a/arch/powerpc/boot/dts/mpc8568mds.dts
+++ b/arch/powerpc/boot/dts/mpc8568mds.dts
@@ -142,7 +142,7 @@
};
enet0: ethernet@24000 {
- cell-index = <0>;
+ fsl,ucc = <0>;
device_type = "network";
model = "eTSEC";
compatible = "gianfar";
@@ -154,7 +154,7 @@
};
enet1: ethernet@25000 {
- cell-index = <1>;
+ fsl,ucc = <1>;
device_type = "network";
model = "eTSEC";
compatible = "gianfar";
@@ -324,9 +324,7 @@
enet2: ucc@2000 {
device_type = "network";
compatible = "ucc_geth";
- model = "UCC";
- cell-index = <1>;
- device-id = <1>;
+ fsl,ucc = <1>;
reg = <2000 200>;
interrupts = <20>;
interrupt-parent = <&qeic>;
@@ -341,9 +339,7 @@
enet3: ucc@3000 {
device_type = "network";
compatible = "ucc_geth";
- model = "UCC";
- cell-index = <2>;
- device-id = <2>;
+ fsl,ucc = <2>;
reg = <3000 200>;
interrupts = <21>;
interrupt-parent = <&qeic>;
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index fba0811..aa6566e 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3852,7 +3852,13 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
ugeth_vdbg("%s: IN", __FUNCTION__);
- prop = of_get_property(np, "device-id", NULL);
+ prop = of_get_property(np, "fsl,ucc", NULL);
+ if (!prop) {
+ prop = of_get_property(np, "device-id", NULL);
+ if (!prop)
+ return -ENODEV;
+ }
+
ucc_num = *prop - 1;
if ((ucc_num < 0) || (ucc_num > 7))
return -ENODEV;
diff --git a/drivers/net/ucc_geth_mii.c b/drivers/net/ucc_geth_mii.c
index c69e654..1d4bfc0 100644
--- a/drivers/net/ucc_geth_mii.c
+++ b/drivers/net/ucc_geth_mii.c
@@ -203,9 +203,14 @@ static int uec_mdio_probe(struct of_device *ofdev, const struct of_device_id *ma
if ((res.start >= tempres.start) &&
(res.end <= tempres.end)) {
/* set this UCC to be the MII master */
- const u32 *id = of_get_property(tempnp, "device-id", NULL);
- if (id == NULL)
- goto bus_register_fail;
+ const u32 *id;
+
+ id = of_get_property(tempnp, "fsl,ucc", NULL);
+ if (!id) {
+ id = of_get_property(tempnp, "device-id", NULL);
+ if (!id)
+ goto bus_register_fail;
+ }
ucc_set_qe_mux_mii_mng(*id - 1);
diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c
index e0994f0..03f49c4 100644
--- a/drivers/serial/ucc_uart.c
+++ b/drivers/serial/ucc_uart.c
@@ -1270,10 +1270,18 @@ static int ucc_uart_probe(struct of_device *ofdev,
/* Get the UCC number (device ID) */
/* UCCs are numbered 1-7 */
- iprop = of_get_property(np, "device-id", NULL);
- if (!iprop || (*iprop < 1) || (*iprop > UCC_MAX_NUM)) {
- dev_err(&ofdev->dev,
- "missing or invalid UCC specified in device tree\n");
+ iprop = of_get_property(np, "fsl,ucc", NULL);
+ if (!iprop) {
+ iprop = of_get_property(np, "device-id", NULL);
+ if (!iprop) {
+ dev_err(&ofdev->dev, "UCC is unspecified in "
+ "device tree\n");
+ return -EINVAL;
+ }
+ }
+
+ if ((*iprop < 1) || (*iprop > UCC_MAX_NUM)) {
+ dev_err(&ofdev->dev, "no support for UCC%u\n", *iprop);
kfree(qe_port);
return -ENODEV;
}
--
1.5.2.2
^ permalink raw reply related
* [PATCH 0/8] A bit of new code and sparse cleanups along the way
From: Anton Vorontsov @ 2008-03-11 17:21 UTC (permalink / raw)
To: linuxppc-dev
Hi all,
Please consider these patches for the 2.6.26.
Thanks,
--
Anton Vorontsov
email: cboumailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply
* [PATCH 1/8] [POWERPC] fsl_elbc_nand: factor out localbus defines
From: Anton Vorontsov @ 2008-03-11 17:23 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Scott Wood, linux-mtd
In-Reply-To: <20080311172106.GA4766@localhost.localdomain>
This is needed to support other localbus peripherals, such as
NAND on FSL UPM.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
Would be great if someone from the MTD community will ack this patch
to go through powerpc trees.
Thanks,
drivers/mtd/nand/fsl_elbc_nand.c | 219 ++-----------------------------------
include/asm-powerpc/fsl_lbc.h | 223 ++++++++++++++++++++++++++++++++++++++
2 files changed, 235 insertions(+), 207 deletions(-)
create mode 100644 include/asm-powerpc/fsl_lbc.h
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index b025dfe..378b7aa 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -36,207 +36,12 @@
#include <linux/mtd/partitions.h>
#include <asm/io.h>
-
+#include <asm/fsl_lbc.h>
#define MAX_BANKS 8
#define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */
#define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */
-struct elbc_bank {
- __be32 br; /**< Base Register */
-#define BR_BA 0xFFFF8000
-#define BR_BA_SHIFT 15
-#define BR_PS 0x00001800
-#define BR_PS_SHIFT 11
-#define BR_PS_8 0x00000800 /* Port Size 8 bit */
-#define BR_PS_16 0x00001000 /* Port Size 16 bit */
-#define BR_PS_32 0x00001800 /* Port Size 32 bit */
-#define BR_DECC 0x00000600
-#define BR_DECC_SHIFT 9
-#define BR_DECC_OFF 0x00000000 /* HW ECC checking and generation off */
-#define BR_DECC_CHK 0x00000200 /* HW ECC checking on, generation off */
-#define BR_DECC_CHK_GEN 0x00000400 /* HW ECC checking and generation on */
-#define BR_WP 0x00000100
-#define BR_WP_SHIFT 8
-#define BR_MSEL 0x000000E0
-#define BR_MSEL_SHIFT 5
-#define BR_MS_GPCM 0x00000000 /* GPCM */
-#define BR_MS_FCM 0x00000020 /* FCM */
-#define BR_MS_SDRAM 0x00000060 /* SDRAM */
-#define BR_MS_UPMA 0x00000080 /* UPMA */
-#define BR_MS_UPMB 0x000000A0 /* UPMB */
-#define BR_MS_UPMC 0x000000C0 /* UPMC */
-#define BR_V 0x00000001
-#define BR_V_SHIFT 0
-#define BR_RES ~(BR_BA|BR_PS|BR_DECC|BR_WP|BR_MSEL|BR_V)
-
- __be32 or; /**< Base Register */
-#define OR0 0x5004
-#define OR1 0x500C
-#define OR2 0x5014
-#define OR3 0x501C
-#define OR4 0x5024
-#define OR5 0x502C
-#define OR6 0x5034
-#define OR7 0x503C
-
-#define OR_FCM_AM 0xFFFF8000
-#define OR_FCM_AM_SHIFT 15
-#define OR_FCM_BCTLD 0x00001000
-#define OR_FCM_BCTLD_SHIFT 12
-#define OR_FCM_PGS 0x00000400
-#define OR_FCM_PGS_SHIFT 10
-#define OR_FCM_CSCT 0x00000200
-#define OR_FCM_CSCT_SHIFT 9
-#define OR_FCM_CST 0x00000100
-#define OR_FCM_CST_SHIFT 8
-#define OR_FCM_CHT 0x00000080
-#define OR_FCM_CHT_SHIFT 7
-#define OR_FCM_SCY 0x00000070
-#define OR_FCM_SCY_SHIFT 4
-#define OR_FCM_SCY_1 0x00000010
-#define OR_FCM_SCY_2 0x00000020
-#define OR_FCM_SCY_3 0x00000030
-#define OR_FCM_SCY_4 0x00000040
-#define OR_FCM_SCY_5 0x00000050
-#define OR_FCM_SCY_6 0x00000060
-#define OR_FCM_SCY_7 0x00000070
-#define OR_FCM_RST 0x00000008
-#define OR_FCM_RST_SHIFT 3
-#define OR_FCM_TRLX 0x00000004
-#define OR_FCM_TRLX_SHIFT 2
-#define OR_FCM_EHTR 0x00000002
-#define OR_FCM_EHTR_SHIFT 1
-};
-
-struct elbc_regs {
- struct elbc_bank bank[8];
- u8 res0[0x28];
- __be32 mar; /**< UPM Address Register */
- u8 res1[0x4];
- __be32 mamr; /**< UPMA Mode Register */
- __be32 mbmr; /**< UPMB Mode Register */
- __be32 mcmr; /**< UPMC Mode Register */
- u8 res2[0x8];
- __be32 mrtpr; /**< Memory Refresh Timer Prescaler Register */
- __be32 mdr; /**< UPM Data Register */
- u8 res3[0x4];
- __be32 lsor; /**< Special Operation Initiation Register */
- __be32 lsdmr; /**< SDRAM Mode Register */
- u8 res4[0x8];
- __be32 lurt; /**< UPM Refresh Timer */
- __be32 lsrt; /**< SDRAM Refresh Timer */
- u8 res5[0x8];
- __be32 ltesr; /**< Transfer Error Status Register */
-#define LTESR_BM 0x80000000
-#define LTESR_FCT 0x40000000
-#define LTESR_PAR 0x20000000
-#define LTESR_WP 0x04000000
-#define LTESR_ATMW 0x00800000
-#define LTESR_ATMR 0x00400000
-#define LTESR_CS 0x00080000
-#define LTESR_CC 0x00000001
-#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
- __be32 ltedr; /**< Transfer Error Disable Register */
- __be32 lteir; /**< Transfer Error Interrupt Register */
- __be32 lteatr; /**< Transfer Error Attributes Register */
- __be32 ltear; /**< Transfer Error Address Register */
- u8 res6[0xC];
- __be32 lbcr; /**< Configuration Register */
-#define LBCR_LDIS 0x80000000
-#define LBCR_LDIS_SHIFT 31
-#define LBCR_BCTLC 0x00C00000
-#define LBCR_BCTLC_SHIFT 22
-#define LBCR_AHD 0x00200000
-#define LBCR_LPBSE 0x00020000
-#define LBCR_LPBSE_SHIFT 17
-#define LBCR_EPAR 0x00010000
-#define LBCR_EPAR_SHIFT 16
-#define LBCR_BMT 0x0000FF00
-#define LBCR_BMT_SHIFT 8
-#define LBCR_INIT 0x00040000
- __be32 lcrr; /**< Clock Ratio Register */
-#define LCRR_DBYP 0x80000000
-#define LCRR_DBYP_SHIFT 31
-#define LCRR_BUFCMDC 0x30000000
-#define LCRR_BUFCMDC_SHIFT 28
-#define LCRR_ECL 0x03000000
-#define LCRR_ECL_SHIFT 24
-#define LCRR_EADC 0x00030000
-#define LCRR_EADC_SHIFT 16
-#define LCRR_CLKDIV 0x0000000F
-#define LCRR_CLKDIV_SHIFT 0
- u8 res7[0x8];
- __be32 fmr; /**< Flash Mode Register */
-#define FMR_CWTO 0x0000F000
-#define FMR_CWTO_SHIFT 12
-#define FMR_BOOT 0x00000800
-#define FMR_ECCM 0x00000100
-#define FMR_AL 0x00000030
-#define FMR_AL_SHIFT 4
-#define FMR_OP 0x00000003
-#define FMR_OP_SHIFT 0
- __be32 fir; /**< Flash Instruction Register */
-#define FIR_OP0 0xF0000000
-#define FIR_OP0_SHIFT 28
-#define FIR_OP1 0x0F000000
-#define FIR_OP1_SHIFT 24
-#define FIR_OP2 0x00F00000
-#define FIR_OP2_SHIFT 20
-#define FIR_OP3 0x000F0000
-#define FIR_OP3_SHIFT 16
-#define FIR_OP4 0x0000F000
-#define FIR_OP4_SHIFT 12
-#define FIR_OP5 0x00000F00
-#define FIR_OP5_SHIFT 8
-#define FIR_OP6 0x000000F0
-#define FIR_OP6_SHIFT 4
-#define FIR_OP7 0x0000000F
-#define FIR_OP7_SHIFT 0
-#define FIR_OP_NOP 0x0 /* No operation and end of sequence */
-#define FIR_OP_CA 0x1 /* Issue current column address */
-#define FIR_OP_PA 0x2 /* Issue current block+page address */
-#define FIR_OP_UA 0x3 /* Issue user defined address */
-#define FIR_OP_CM0 0x4 /* Issue command from FCR[CMD0] */
-#define FIR_OP_CM1 0x5 /* Issue command from FCR[CMD1] */
-#define FIR_OP_CM2 0x6 /* Issue command from FCR[CMD2] */
-#define FIR_OP_CM3 0x7 /* Issue command from FCR[CMD3] */
-#define FIR_OP_WB 0x8 /* Write FBCR bytes from FCM buffer */
-#define FIR_OP_WS 0x9 /* Write 1 or 2 bytes from MDR[AS] */
-#define FIR_OP_RB 0xA /* Read FBCR bytes to FCM buffer */
-#define FIR_OP_RS 0xB /* Read 1 or 2 bytes to MDR[AS] */
-#define FIR_OP_CW0 0xC /* Wait then issue FCR[CMD0] */
-#define FIR_OP_CW1 0xD /* Wait then issue FCR[CMD1] */
-#define FIR_OP_RBW 0xE /* Wait then read FBCR bytes */
-#define FIR_OP_RSW 0xE /* Wait then read 1 or 2 bytes */
- __be32 fcr; /**< Flash Command Register */
-#define FCR_CMD0 0xFF000000
-#define FCR_CMD0_SHIFT 24
-#define FCR_CMD1 0x00FF0000
-#define FCR_CMD1_SHIFT 16
-#define FCR_CMD2 0x0000FF00
-#define FCR_CMD2_SHIFT 8
-#define FCR_CMD3 0x000000FF
-#define FCR_CMD3_SHIFT 0
- __be32 fbar; /**< Flash Block Address Register */
-#define FBAR_BLK 0x00FFFFFF
- __be32 fpar; /**< Flash Page Address Register */
-#define FPAR_SP_PI 0x00007C00
-#define FPAR_SP_PI_SHIFT 10
-#define FPAR_SP_MS 0x00000200
-#define FPAR_SP_CI 0x000001FF
-#define FPAR_SP_CI_SHIFT 0
-#define FPAR_LP_PI 0x0003F000
-#define FPAR_LP_PI_SHIFT 12
-#define FPAR_LP_MS 0x00000800
-#define FPAR_LP_CI 0x000007FF
-#define FPAR_LP_CI_SHIFT 0
- __be32 fbcr; /**< Flash Byte Count Register */
-#define FBCR_BC 0x00000FFF
- u8 res11[0x8];
- u8 res8[0xF00];
-};
-
struct fsl_elbc_ctrl;
/* mtd information per set */
@@ -261,7 +66,7 @@ struct fsl_elbc_ctrl {
/* device info */
struct device *dev;
- struct elbc_regs __iomem *regs;
+ struct fsl_lbc_regs __iomem *regs;
int irq;
wait_queue_head_t irq_wait;
unsigned int irq_status; /* status read from LTESR by irq handler */
@@ -322,7 +127,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- struct elbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
int buf_num;
ctrl->page = page_addr;
@@ -363,7 +168,7 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- struct elbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
/* Setup the FMR[OP] to execute without write protection */
out_be32(&lbc->fmr, priv->fmr | 3);
@@ -406,7 +211,7 @@ static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
{
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- struct elbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
if (priv->page_size) {
out_be32(&lbc->fir,
@@ -439,7 +244,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- struct elbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
ctrl->use_mdr = 0;
@@ -775,7 +580,7 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
{
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- struct elbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
if (ctrl->status != LTESR_CC)
return NAND_STATUS_FAIL;
@@ -807,7 +612,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- struct elbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
unsigned int al;
/* calculate FMR Address Length field */
@@ -922,7 +727,7 @@ static void fsl_elbc_write_page(struct mtd_info *mtd,
static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
{
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- struct elbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
struct nand_chip *chip = &priv->chip;
dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
@@ -986,7 +791,7 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
static int fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
struct device_node *node)
{
- struct elbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
struct fsl_elbc_mtd *priv;
struct resource res;
#ifdef CONFIG_MTD_PARTITIONS
@@ -1083,7 +888,7 @@ err:
static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl)
{
- struct elbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
/* clear event registers */
setbits32(&lbc->ltesr, LTESR_NAND_MASK);
@@ -1128,7 +933,7 @@ static int __devexit fsl_elbc_ctrl_remove(struct of_device *ofdev)
static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data)
{
struct fsl_elbc_ctrl *ctrl = data;
- struct elbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
__be32 status = in_be32(&lbc->ltesr) & LTESR_NAND_MASK;
if (status) {
diff --git a/include/asm-powerpc/fsl_lbc.h b/include/asm-powerpc/fsl_lbc.h
new file mode 100644
index 0000000..13a3c28
--- /dev/null
+++ b/include/asm-powerpc/fsl_lbc.h
@@ -0,0 +1,223 @@
+/* Freescale Local Bus Controller
+ *
+ * Copyright (c) 2006-2007 Freescale Semiconductor
+ *
+ * Authors: Nick Spence <nick.spence@freescale.com>,
+ * Scott Wood <scottwood@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ASM_FSL_LBC_H
+#define __ASM_FSL_LBC_H
+
+#include <linux/types.h>
+
+struct fsl_lbc_bank {
+ __be32 br; /**< Base Register */
+#define BR_BA 0xFFFF8000
+#define BR_BA_SHIFT 15
+#define BR_PS 0x00001800
+#define BR_PS_SHIFT 11
+#define BR_PS_8 0x00000800 /* Port Size 8 bit */
+#define BR_PS_16 0x00001000 /* Port Size 16 bit */
+#define BR_PS_32 0x00001800 /* Port Size 32 bit */
+#define BR_DECC 0x00000600
+#define BR_DECC_SHIFT 9
+#define BR_DECC_OFF 0x00000000 /* HW ECC checking and generation off */
+#define BR_DECC_CHK 0x00000200 /* HW ECC checking on, generation off */
+#define BR_DECC_CHK_GEN 0x00000400 /* HW ECC checking and generation on */
+#define BR_WP 0x00000100
+#define BR_WP_SHIFT 8
+#define BR_MSEL 0x000000E0
+#define BR_MSEL_SHIFT 5
+#define BR_MS_GPCM 0x00000000 /* GPCM */
+#define BR_MS_FCM 0x00000020 /* FCM */
+#define BR_MS_SDRAM 0x00000060 /* SDRAM */
+#define BR_MS_UPMA 0x00000080 /* UPMA */
+#define BR_MS_UPMB 0x000000A0 /* UPMB */
+#define BR_MS_UPMC 0x000000C0 /* UPMC */
+#define BR_V 0x00000001
+#define BR_V_SHIFT 0
+#define BR_RES ~(BR_BA|BR_PS|BR_DECC|BR_WP|BR_MSEL|BR_V)
+
+ __be32 or; /**< Base Register */
+#define OR0 0x5004
+#define OR1 0x500C
+#define OR2 0x5014
+#define OR3 0x501C
+#define OR4 0x5024
+#define OR5 0x502C
+#define OR6 0x5034
+#define OR7 0x503C
+
+#define OR_FCM_AM 0xFFFF8000
+#define OR_FCM_AM_SHIFT 15
+#define OR_FCM_BCTLD 0x00001000
+#define OR_FCM_BCTLD_SHIFT 12
+#define OR_FCM_PGS 0x00000400
+#define OR_FCM_PGS_SHIFT 10
+#define OR_FCM_CSCT 0x00000200
+#define OR_FCM_CSCT_SHIFT 9
+#define OR_FCM_CST 0x00000100
+#define OR_FCM_CST_SHIFT 8
+#define OR_FCM_CHT 0x00000080
+#define OR_FCM_CHT_SHIFT 7
+#define OR_FCM_SCY 0x00000070
+#define OR_FCM_SCY_SHIFT 4
+#define OR_FCM_SCY_1 0x00000010
+#define OR_FCM_SCY_2 0x00000020
+#define OR_FCM_SCY_3 0x00000030
+#define OR_FCM_SCY_4 0x00000040
+#define OR_FCM_SCY_5 0x00000050
+#define OR_FCM_SCY_6 0x00000060
+#define OR_FCM_SCY_7 0x00000070
+#define OR_FCM_RST 0x00000008
+#define OR_FCM_RST_SHIFT 3
+#define OR_FCM_TRLX 0x00000004
+#define OR_FCM_TRLX_SHIFT 2
+#define OR_FCM_EHTR 0x00000002
+#define OR_FCM_EHTR_SHIFT 1
+};
+
+struct fsl_lbc_regs {
+ struct fsl_lbc_bank bank[8];
+ u8 res0[0x28];
+ __be32 mar; /**< UPM Address Register */
+ u8 res1[0x4];
+ __be32 mamr; /**< UPMA Mode Register */
+ __be32 mbmr; /**< UPMB Mode Register */
+ __be32 mcmr; /**< UPMC Mode Register */
+ u8 res2[0x8];
+ __be32 mrtpr; /**< Memory Refresh Timer Prescaler Register */
+ __be32 mdr; /**< UPM Data Register */
+ u8 res3[0x4];
+ __be32 lsor; /**< Special Operation Initiation Register */
+ __be32 lsdmr; /**< SDRAM Mode Register */
+ u8 res4[0x8];
+ __be32 lurt; /**< UPM Refresh Timer */
+ __be32 lsrt; /**< SDRAM Refresh Timer */
+ u8 res5[0x8];
+ __be32 ltesr; /**< Transfer Error Status Register */
+#define LTESR_BM 0x80000000
+#define LTESR_FCT 0x40000000
+#define LTESR_PAR 0x20000000
+#define LTESR_WP 0x04000000
+#define LTESR_ATMW 0x00800000
+#define LTESR_ATMR 0x00400000
+#define LTESR_CS 0x00080000
+#define LTESR_CC 0x00000001
+#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
+ __be32 ltedr; /**< Transfer Error Disable Register */
+ __be32 lteir; /**< Transfer Error Interrupt Register */
+ __be32 lteatr; /**< Transfer Error Attributes Register */
+ __be32 ltear; /**< Transfer Error Address Register */
+ u8 res6[0xC];
+ __be32 lbcr; /**< Configuration Register */
+#define LBCR_LDIS 0x80000000
+#define LBCR_LDIS_SHIFT 31
+#define LBCR_BCTLC 0x00C00000
+#define LBCR_BCTLC_SHIFT 22
+#define LBCR_AHD 0x00200000
+#define LBCR_LPBSE 0x00020000
+#define LBCR_LPBSE_SHIFT 17
+#define LBCR_EPAR 0x00010000
+#define LBCR_EPAR_SHIFT 16
+#define LBCR_BMT 0x0000FF00
+#define LBCR_BMT_SHIFT 8
+#define LBCR_INIT 0x00040000
+ __be32 lcrr; /**< Clock Ratio Register */
+#define LCRR_DBYP 0x80000000
+#define LCRR_DBYP_SHIFT 31
+#define LCRR_BUFCMDC 0x30000000
+#define LCRR_BUFCMDC_SHIFT 28
+#define LCRR_ECL 0x03000000
+#define LCRR_ECL_SHIFT 24
+#define LCRR_EADC 0x00030000
+#define LCRR_EADC_SHIFT 16
+#define LCRR_CLKDIV 0x0000000F
+#define LCRR_CLKDIV_SHIFT 0
+ u8 res7[0x8];
+ __be32 fmr; /**< Flash Mode Register */
+#define FMR_CWTO 0x0000F000
+#define FMR_CWTO_SHIFT 12
+#define FMR_BOOT 0x00000800
+#define FMR_ECCM 0x00000100
+#define FMR_AL 0x00000030
+#define FMR_AL_SHIFT 4
+#define FMR_OP 0x00000003
+#define FMR_OP_SHIFT 0
+ __be32 fir; /**< Flash Instruction Register */
+#define FIR_OP0 0xF0000000
+#define FIR_OP0_SHIFT 28
+#define FIR_OP1 0x0F000000
+#define FIR_OP1_SHIFT 24
+#define FIR_OP2 0x00F00000
+#define FIR_OP2_SHIFT 20
+#define FIR_OP3 0x000F0000
+#define FIR_OP3_SHIFT 16
+#define FIR_OP4 0x0000F000
+#define FIR_OP4_SHIFT 12
+#define FIR_OP5 0x00000F00
+#define FIR_OP5_SHIFT 8
+#define FIR_OP6 0x000000F0
+#define FIR_OP6_SHIFT 4
+#define FIR_OP7 0x0000000F
+#define FIR_OP7_SHIFT 0
+#define FIR_OP_NOP 0x0 /* No operation and end of sequence */
+#define FIR_OP_CA 0x1 /* Issue current column address */
+#define FIR_OP_PA 0x2 /* Issue current block+page address */
+#define FIR_OP_UA 0x3 /* Issue user defined address */
+#define FIR_OP_CM0 0x4 /* Issue command from FCR[CMD0] */
+#define FIR_OP_CM1 0x5 /* Issue command from FCR[CMD1] */
+#define FIR_OP_CM2 0x6 /* Issue command from FCR[CMD2] */
+#define FIR_OP_CM3 0x7 /* Issue command from FCR[CMD3] */
+#define FIR_OP_WB 0x8 /* Write FBCR bytes from FCM buffer */
+#define FIR_OP_WS 0x9 /* Write 1 or 2 bytes from MDR[AS] */
+#define FIR_OP_RB 0xA /* Read FBCR bytes to FCM buffer */
+#define FIR_OP_RS 0xB /* Read 1 or 2 bytes to MDR[AS] */
+#define FIR_OP_CW0 0xC /* Wait then issue FCR[CMD0] */
+#define FIR_OP_CW1 0xD /* Wait then issue FCR[CMD1] */
+#define FIR_OP_RBW 0xE /* Wait then read FBCR bytes */
+#define FIR_OP_RSW 0xE /* Wait then read 1 or 2 bytes */
+ __be32 fcr; /**< Flash Command Register */
+#define FCR_CMD0 0xFF000000
+#define FCR_CMD0_SHIFT 24
+#define FCR_CMD1 0x00FF0000
+#define FCR_CMD1_SHIFT 16
+#define FCR_CMD2 0x0000FF00
+#define FCR_CMD2_SHIFT 8
+#define FCR_CMD3 0x000000FF
+#define FCR_CMD3_SHIFT 0
+ __be32 fbar; /**< Flash Block Address Register */
+#define FBAR_BLK 0x00FFFFFF
+ __be32 fpar; /**< Flash Page Address Register */
+#define FPAR_SP_PI 0x00007C00
+#define FPAR_SP_PI_SHIFT 10
+#define FPAR_SP_MS 0x00000200
+#define FPAR_SP_CI 0x000001FF
+#define FPAR_SP_CI_SHIFT 0
+#define FPAR_LP_PI 0x0003F000
+#define FPAR_LP_PI_SHIFT 12
+#define FPAR_LP_MS 0x00000800
+#define FPAR_LP_CI 0x000007FF
+#define FPAR_LP_CI_SHIFT 0
+ __be32 fbcr; /**< Flash Byte Count Register */
+#define FBCR_BC 0x00000FFF
+ u8 res11[0x8];
+ u8 res8[0xF00];
+};
+
+#endif /* __ASM_FSL_LBC_H */
--
1.5.2.2
^ permalink raw reply related
* [PATCH 2/8] [POWERPC] fsl_lbc: implement few routines to manage FSL UPMs
From: Anton Vorontsov @ 2008-03-11 17:24 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20080311172106.GA4766@localhost.localdomain>
These will be used by the FSL UPM NAND driver.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
arch/powerpc/Kconfig | 5 ++
arch/powerpc/sysdev/Makefile | 1 +
arch/powerpc/sysdev/fsl_lbc.c | 99 +++++++++++++++++++++++++++++++++++++++++
include/asm-powerpc/fsl_lbc.h | 63 ++++++++++++++++++++++++++
4 files changed, 168 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/sysdev/fsl_lbc.c
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index ef12db0..9c68592 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -491,6 +491,11 @@ config FSL_PCI
bool
select PPC_INDIRECT_PCI
+config FSL_LBC
+ bool
+ help
+ Freescale Localbus support
+
# Yes MCA RS/6000s exist but Linux-PPC does not currently support any
config MCA
bool
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 15f3e85..62b6ef0 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_U3_DART) += dart_iommu.o
obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
obj-$(CONFIG_FSL_SOC) += fsl_soc.o
obj-$(CONFIG_FSL_PCI) += fsl_pci.o
+obj-$(CONFIG_FSL_LBC) += fsl_lbc.o
obj-$(CONFIG_RAPIDIO) += fsl_rio.o
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
new file mode 100644
index 0000000..b59f2f4
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_lbc.c
@@ -0,0 +1,99 @@
+/*
+ * Freescale UPM routines.
+ *
+ * Copyright (c) 2007-2008 MontaVista Software, Inc.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * 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/kernel.h>
+#include <linux/of.h>
+#include <asm/fsl_lbc.h>
+
+spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
+
+struct fsl_lbc_regs __iomem *fsl_lbc_regs;
+EXPORT_SYMBOL(fsl_lbc_regs);
+
+static char __initdata *compat_lbc[] = {
+ "fsl,pq2-localbus",
+ "fsl,pq2pro-localbus",
+ "fsl,pq3-localbus",
+ "fsl,elbc",
+};
+
+static int __init fsl_lbc_init(void)
+{
+ struct device_node *lbus;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) {
+ lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]);
+ if (lbus)
+ goto found;
+ }
+ return -ENODEV;
+
+found:
+ fsl_lbc_regs = of_iomap(lbus, 0);
+ of_node_put(lbus);
+ if (!fsl_lbc_regs)
+ return -ENOMEM;
+ return 0;
+}
+arch_initcall(fsl_lbc_init);
+
+int fsl_upm_find(u32 base, struct fsl_upm *upm)
+{
+ int i;
+ __be32 br;
+ __be32 or;
+
+ if (!fsl_lbc_regs)
+ return -ENODEV;
+
+ for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) {
+ br = in_be32(&fsl_lbc_regs->bank[i].br);
+ or = in_be32(&fsl_lbc_regs->bank[i].or);
+
+ if (br & BR_V && (br & or & BR_BA) == base)
+ goto found;
+ }
+
+ return -ENOENT;
+found:
+ switch (br & BR_MSEL) {
+ case BR_MS_UPMA:
+ upm->mxmr = &fsl_lbc_regs->mamr;
+ break;
+ case BR_MS_UPMB:
+ upm->mxmr = &fsl_lbc_regs->mbmr;
+ break;
+ case BR_MS_UPMC:
+ upm->mxmr = &fsl_lbc_regs->mcmr;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (br & BR_PS) {
+ case BR_PS_8:
+ upm->width = 8;
+ break;
+ case BR_PS_16:
+ upm->width = 16;
+ break;
+ case BR_PS_32:
+ upm->width = 32;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/include/asm-powerpc/fsl_lbc.h b/include/asm-powerpc/fsl_lbc.h
index 13a3c28..a6b99a3 100644
--- a/include/asm-powerpc/fsl_lbc.h
+++ b/include/asm-powerpc/fsl_lbc.h
@@ -24,6 +24,8 @@
#define __ASM_FSL_LBC_H
#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
struct fsl_lbc_bank {
__be32 br; /**< Base Register */
@@ -98,6 +100,11 @@ struct fsl_lbc_regs {
__be32 mar; /**< UPM Address Register */
u8 res1[0x4];
__be32 mamr; /**< UPMA Mode Register */
+#define MxMR_OP_NO (0 << 28) /**< normal operation */
+#define MxMR_OP_WA (1 << 28) /**< write array */
+#define MxMR_OP_RA (2 << 28) /**< read array */
+#define MxMR_OP_RP (3 << 28) /**< run pattern */
+#define MxMR_MAD 0x3f /**< machine address */
__be32 mbmr; /**< UPMB Mode Register */
__be32 mcmr; /**< UPMC Mode Register */
u8 res2[0x8];
@@ -220,4 +227,60 @@ struct fsl_lbc_regs {
u8 res8[0xF00];
};
+extern struct fsl_lbc_regs __iomem *fsl_lbc_regs;
+extern spinlock_t fsl_lbc_lock;
+
+/*
+ * FSL UPM routines
+ */
+struct fsl_upm {
+ __be32 __iomem *mxmr;
+ int width;
+};
+
+extern int fsl_upm_find(u32 base, struct fsl_upm *upm);
+
+static inline void fsl_upm_start_pattern(struct fsl_upm *upm, u8 pat_offset)
+{
+ clrsetbits_be32(upm->mxmr, MxMR_MAD, MxMR_OP_RP | pat_offset);
+}
+
+static inline void fsl_upm_end_pattern(struct fsl_upm *upm)
+{
+ clrbits32(upm->mxmr, MxMR_OP_RP);
+
+ while (in_be32(upm->mxmr) & MxMR_OP_RP)
+ cpu_relax();
+}
+
+static inline int fsl_upm_run_pattern(struct fsl_upm *upm,
+ void __iomem *io_base, u32 mar)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fsl_lbc_lock, flags);
+
+ out_be32(&fsl_lbc_regs->mar, mar << (32 - upm->width));
+
+ switch (upm->width) {
+ case 8:
+ out_8(io_base, 0x0);
+ break;
+ case 16:
+ out_be16(io_base, 0x0);
+ break;
+ case 32:
+ out_be32(io_base, 0x0);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ spin_unlock_irqrestore(&fsl_lbc_lock, flags);
+
+ return ret;
+}
+
#endif /* __ASM_FSL_LBC_H */
--
1.5.2.2
^ permalink raw reply related
* [PATCH 3/8] [POWERPC] qe_lib: implement qe_muram_offset
From: Anton Vorontsov @ 2008-03-11 17:24 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20080311172106.GA4766@localhost.localdomain>
qe_muram_offset is the reverse of the qe_muram_addr, will be
used for the Freescale QE USB Host Controller driver.
This patch also moves qe_muram_addr into the qe.h header, plus
adds __iomem hints to use with sparse.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
arch/powerpc/sysdev/qe_lib/qe.c | 8 +-------
include/asm-powerpc/immap_qe.h | 2 +-
include/asm-powerpc/qe.h | 11 ++++++++++-
3 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index 6efbd5e..b444b1d 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -55,7 +55,7 @@ struct qe_snum {
/* We allocate this here because it is used almost exclusively for
* the communication processor devices.
*/
-struct qe_immap *qe_immr = NULL;
+struct qe_immap __iomem *qe_immr;
EXPORT_SYMBOL(qe_immr);
static struct qe_snum snums[QE_NUM_OF_SNUM]; /* Dynamically allocated SNUMs */
@@ -415,12 +415,6 @@ void qe_muram_dump(void)
}
EXPORT_SYMBOL(qe_muram_dump);
-void *qe_muram_addr(unsigned long offset)
-{
- return (void *)&qe_immr->muram[offset];
-}
-EXPORT_SYMBOL(qe_muram_addr);
-
/* The maximum number of RISCs we support */
#define MAX_QE_RISC 2
diff --git a/include/asm-powerpc/immap_qe.h b/include/asm-powerpc/immap_qe.h
index 82a4526..924aefb 100644
--- a/include/asm-powerpc/immap_qe.h
+++ b/include/asm-powerpc/immap_qe.h
@@ -468,7 +468,7 @@ struct qe_immap {
u8 res18[0xC0000]; /* 0x140000 - 0x200000 */
} __attribute__ ((packed));
-extern struct qe_immap *qe_immr;
+extern struct qe_immap __iomem *qe_immr;
extern phys_addr_t get_qe_base(void);
static inline unsigned long immrbar_virt_to_phys(void *address)
diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h
index 430dc77..398534c 100644
--- a/include/asm-powerpc/qe.h
+++ b/include/asm-powerpc/qe.h
@@ -92,7 +92,16 @@ unsigned long qe_muram_alloc(int size, int align);
int qe_muram_free(unsigned long offset);
unsigned long qe_muram_alloc_fixed(unsigned long offset, int size);
void qe_muram_dump(void);
-void *qe_muram_addr(unsigned long offset);
+
+static inline void __iomem *qe_muram_addr(unsigned long offset)
+{
+ return (void __iomem *)&qe_immr->muram[offset];
+}
+
+static inline unsigned long qe_muram_offset(void __iomem *addr)
+{
+ return addr - (void __iomem *)qe_immr->muram;
+}
/* Structure that defines QE firmware binary files.
*
--
1.5.2.2
^ permalink raw reply related
* [PATCH 4/8] [POWERPC] immap_qe.h should include asm/io.h
From: Anton Vorontsov @ 2008-03-11 17:24 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20080311172106.GA4766@localhost.localdomain>
Headers should include prototypes they use, otherwise build will
break if we use it without explicitly including io.h:
CC arch/powerpc/sysdev/qe_lib/gtm.o
In file included from include/asm/qe.h:20,
from arch/powerpc/sysdev/qe_lib/gtm.c:18:
include/asm/immap_qe.h: In function ‘immrbar_virt_to_phys’:
include/asm/immap_qe.h:480: error: implicit declaration of function ‘virt_to_phys’
make[2]: *** [arch/powerpc/sysdev/qe_lib/gtm.o] Error 1
make[1]: *** [arch/powerpc/sysdev/qe_lib] Error 2
gtm.c needs qe.h (which includes immap_qe.h) to use qe_get_brg_clk().
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
include/asm-powerpc/immap_qe.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/include/asm-powerpc/immap_qe.h b/include/asm-powerpc/immap_qe.h
index 924aefb..7b6f411 100644
--- a/include/asm-powerpc/immap_qe.h
+++ b/include/asm-powerpc/immap_qe.h
@@ -20,6 +20,7 @@
#ifdef __KERNEL__
#include <linux/kernel.h>
+#include <asm/io.h>
#define QE_IMMAP_SIZE (1024 * 1024) /* 1MB from 1MB+IMMR */
--
1.5.2.2
^ permalink raw reply related
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