* [PATCH 4/5] fpga: add CARMA DATA-FPGA Access Driver
From: Ira W. Snyder @ 2010-09-08 16:41 UTC (permalink / raw)
To: linuxppc-dev; +Cc: linux-kernel, Ira W. Snyder
In-Reply-To: <1283964082-30133-1-git-send-email-iws@ovro.caltech.edu>
This driver allows userspace to access the data processing FPGAs on the
OVRO CARMA board. It has two modes of operation:
1) random access
This allows users to poke any DATA-FPGA registers by using mmap to map
the address region directly into their memory map.
2) correlation dumping
When correlating, the DATA-FPGA's have special requirements for getting
the data out of their memory before the next correlation. This nominally
happens at 64Hz (every 15.625ms). If the data is not dumped before the
next correlation, data is lost.
The data dumping driver handles buffering up to 1 second worth of
correlation data from the FPGAs. This lowers the realtime scheduling
requirements for the userspace process reading the device.
Signed-off-by: Ira W. Snyder <iws@ovro.caltech.edu>
---
drivers/fpga/carma/Kconfig | 9 +
drivers/fpga/carma/Makefile | 1 +
drivers/fpga/carma/carma-fpga.c | 1471 +++++++++++++++++++++++++++++++++++++++
3 files changed, 1481 insertions(+), 0 deletions(-)
create mode 100644 drivers/fpga/carma/carma-fpga.c
diff --git a/drivers/fpga/carma/Kconfig b/drivers/fpga/carma/Kconfig
index 448885e..13c4662 100644
--- a/drivers/fpga/carma/Kconfig
+++ b/drivers/fpga/carma/Kconfig
@@ -18,4 +18,13 @@ config CARMA
Say Y here to include basic support for the CARMA System Controller
FPGA. This option allows the other more advanced drivers to be built.
+config CARMA_FPGA
+ tristate "CARMA DATA-FPGA Access Driver"
+ depends on CARMA && MEDIA_SUPPORT && HAS_DMA && FSL_DMA
+ select VIDEOBUF_DMA_SG
+ default n
+ help
+ Say Y here to include support for communicating with the data
+ processing FPGAs on the CARMA board.
+
endif # FPGA_DRIVERS
diff --git a/drivers/fpga/carma/Makefile b/drivers/fpga/carma/Makefile
index 90d0594..c175d34 100644
--- a/drivers/fpga/carma/Makefile
+++ b/drivers/fpga/carma/Makefile
@@ -1 +1,2 @@
obj-$(CONFIG_CARMA) += carma.o
+obj-$(CONFIG_CARMA_FPGA) += carma-fpga.o
diff --git a/drivers/fpga/carma/carma-fpga.c b/drivers/fpga/carma/carma-fpga.c
new file mode 100644
index 0000000..9534162
--- /dev/null
+++ b/drivers/fpga/carma/carma-fpga.c
@@ -0,0 +1,1471 @@
+/*
+ * CARMA DATA-FPGA Access Driver
+ *
+ * Copyright (c) 2009-2010 Ira W. Snyder <iws@ovro.caltech.edu>
+ *
+ * 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.
+ */
+
+/*
+ * FPGA Memory Dump Format
+ *
+ * FPGA #0 control registers (32 x 32-bit words)
+ * FPGA #1 control registers (32 x 32-bit words)
+ * FPGA #2 control registers (32 x 32-bit words)
+ * FPGA #3 control registers (32 x 32-bit words)
+ * SYSFPGA control registers (32 x 32-bit words)
+ * FPGA #0 correlation array (NUM_CORL0 correlation blocks)
+ * FPGA #1 correlation array (NUM_CORL1 correlation blocks)
+ * FPGA #2 correlation array (NUM_CORL2 correlation blocks)
+ * FPGA #3 correlation array (NUM_CORL3 correlation blocks)
+ *
+ * Each correlation array consists of:
+ *
+ * Correlation Data (2 x NUM_LAGSn x 32-bit words)
+ * Pipeline Metadata (2 x NUM_METAn x 32-bit words)
+ * Quantization Counters (2 x NUM_QCNTn x 32-bit words)
+ *
+ * The NUM_CORLn, NUM_LAGSn, NUM_METAn, and NUM_QCNTn values come from
+ * the FPGA configuration registers. They do not change once the FPGA's
+ * have been programmed, they only change on re-programming.
+ */
+
+/*
+ * Basic Description:
+ *
+ * This driver is used to capture correlation spectra off of the four data
+ * processing FPGAs. The FPGAs are often reprogrammed at runtime, therefore
+ * this driver supports dynamic enable/disable of capture while the device
+ * remains open.
+ *
+ * The nominal capture rate is 64Hz (every 15.625ms). To facilitate this fast
+ * capture rate, all buffers are pre-allocated to avoid any potentially long
+ * running memory allocations while capturing.
+ *
+ * There are three lists which are used to keep track of the different states
+ * of data buffers.
+ *
+ * 1) free list
+ * This list holds all empty data buffers which are ready to receive data.
+ *
+ * 2) inflight list
+ * This list holds data buffers which are currently waiting for a DMA operation
+ * to complete.
+ *
+ * 3) used list
+ * This list holds data buffers which have been filled, and are waiting to be
+ * read by userspace.
+ *
+ * All buffers start life on the free list, then move successively to the
+ * inflight list, and then to the used list. After they have been read by
+ * userspace, they are moved back to the free list. The cycle repeats as long
+ * as necessary.
+ */
+
+/*
+ * Notes on the IRQ masking scheme:
+ *
+ * The IRQ masking scheme here is different than most other hardware. The only
+ * way for the DATA-FPGAs to detect if the kernel has taken too long to copy
+ * the data is if the status registers are not cleared before the next
+ * correlation data dump is ready.
+ *
+ * The interrupt line is connected to the status registers, such that when they
+ * are cleared, the interrupt is de-asserted. Therein lies our problem. We need
+ * to schedule a long-running DMA operation and return from the interrupt
+ * handler quickly, but we cannot clear the status registers.
+ *
+ * To handle this, the system controller FPGA has the capability to connect the
+ * interrupt line to a user-controlled GPIO pin. This pin is driven high
+ * (unasserted) and left that way. To mask the interrupt, we change the
+ * interrupt source to the GPIO pin. Tada, we hid the interrupt. :)
+ */
+
+#include <linux/of_platform.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/dmaengine.h>
+#include <linux/highmem.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/cdev.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <media/videobuf-dma-sg.h>
+#include <asm/fsldma.h>
+
+#include "carma.h"
+
+/* system controller registers */
+#define SYS_IRQ_SOURCE_CTL 0x24
+#define SYS_IRQ_OUTPUT_EN 0x28
+#define SYS_IRQ_OUTPUT_DATA 0x2C
+#define SYS_IRQ_INPUT_DATA 0x30
+
+/* GPIO IRQ line assignment */
+#define IRQ_CORL_DONE 0x10
+
+/* FPGA registers */
+#define MMAP_REG_CORL_CONF1 0x08
+#define MMAP_REG_CORL_CONF2 0x0C
+#define MMAP_REG_STATUS 0x48
+
+#define SYS_FPGA_BLOCK 0xF0000000
+
+static const char drv_name[] = "carma-fpga";
+
+#define NUM_FPGA 4
+
+#define MIN_DATA_BUFS 8
+#define MAX_DATA_BUFS 64
+
+struct fpga_info {
+ unsigned int num_corl;
+ unsigned int blk_size;
+};
+
+struct data_buf {
+ struct list_head entry;
+ struct videobuf_dmabuf vb;
+ bool mapped;
+ size_t size;
+};
+
+struct fpga_device {
+ struct cdev cdev;
+ dev_t devno;
+
+ struct device *dev;
+ struct mutex mutex;
+
+ /* FPGA registers and information */
+ struct fpga_info info[NUM_FPGA];
+ void __iomem *regs;
+ int irq;
+
+ /* FPGA Physical Address/Size Information */
+ resource_size_t phys_addr;
+ size_t phys_size;
+
+ /* DMA structures */
+ struct fsl_dma_slave *slave;
+ struct dma_chan *chan;
+ struct device *dmadev;
+
+ /* Protection for all members below */
+ spinlock_t lock;
+
+ /* Device enable/disable flag */
+ bool enabled;
+
+ /* Correlation data buffers */
+ wait_queue_head_t wait;
+ struct list_head free;
+ struct list_head used;
+ struct list_head inflight;
+
+ /* Information about data buffers */
+ unsigned int num_dropped;
+ unsigned int num_buffers;
+ size_t bufsize;
+};
+
+struct fpga_reader {
+ struct fpga_device *priv;
+ struct data_buf *buf;
+ off_t buf_start;
+};
+
+#define inode_to_dev(inode) container_of(inode->i_cdev, struct fpga_device, cdev)
+
+/*
+ * Data Buffer Allocation Helpers
+ */
+
+static int data_map_buffer(struct device *dev, struct data_buf *buf)
+{
+ int ret;
+
+ /* if the buffer is already mapped, we're done */
+ if (buf->mapped)
+ return 0;
+
+ ret = videobuf_dma_map(dev, &buf->vb);
+ if (ret)
+ return ret;
+
+ buf->mapped = true;
+ return 0;
+}
+
+static void data_unmap_buffer(struct device *dev, struct data_buf *buf)
+{
+ /* the buffer is already unmapped, we're done */
+ if (!buf->mapped)
+ return;
+
+ videobuf_dma_unmap(dev, &buf->vb);
+ buf->mapped = false;
+}
+
+/**
+ * data_free_buffer() - free a single data buffer and all allocated memory
+ * @dev: the DMA device to map for
+ * @buf: the buffer to free
+ *
+ * This will free all of the pages allocated to the given data buffer, and
+ * then free the structure itself
+ */
+static void data_free_buffer(struct device *dev, struct data_buf *buf)
+{
+ /* It is ok to free a NULL buffer */
+ if (!buf)
+ return;
+
+ /* Make sure the buffer is not on any list */
+ list_del_init(&buf->entry);
+
+ /* unmap it for DMA */
+ data_unmap_buffer(dev, buf);
+
+ /* free all memory */
+ videobuf_dma_free(&buf->vb);
+ kfree(buf);
+}
+
+/**
+ * data_alloc_buffer() - allocate and fill a data buffer with pages
+ * @dev: the DMA device to map for
+ * @bytes: the number of bytes required
+ *
+ * This allocates all space needed for a data buffer, and gets it ready to be
+ * used in a DMA transaction. It only needs to be used, never mapped before
+ * use. This avoids calling vmalloc in hardirq context.
+ *
+ * Returns NULL on failure
+ */
+static struct data_buf *data_alloc_buffer(struct device *dev, const size_t bytes)
+{
+ unsigned int nr_pages;
+ struct data_buf *buf;
+ int ret;
+
+ /* calculate the number of pages necessary */
+ nr_pages = DIV_ROUND_UP(bytes, PAGE_SIZE);
+
+ /* allocate the buffer structure */
+ buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+ if (!buf)
+ goto out_return;
+
+ /* initialize internal fields */
+ INIT_LIST_HEAD(&buf->entry);
+ buf->size = bytes;
+
+ /* allocate the videobuf */
+ videobuf_dma_init(&buf->vb);
+ ret = videobuf_dma_init_kernel(&buf->vb, DMA_FROM_DEVICE, nr_pages);
+ if (ret)
+ goto out_free_buf;
+
+ /* map it for DMA */
+ ret = data_map_buffer(dev, buf);
+ if (ret)
+ goto out_free_videobuf;
+
+ return buf;
+
+out_free_videobuf:
+ videobuf_dma_free(&buf->vb);
+out_free_buf:
+ kfree(buf);
+out_return:
+ return NULL;
+}
+
+/**
+ * data_free_buffers() - free all allocated buffers
+ * @priv: the driver's private data structure
+ *
+ * Free all buffers allocated by the driver (except those currently in the
+ * process of being read by userspace).
+ *
+ * LOCKING: must hold dev->mutex
+ * CONTEXT: user
+ */
+static void data_free_buffers(struct fpga_device *priv)
+{
+ struct device *dev = priv->dmadev;
+ struct data_buf *buf, *tmp;
+
+ spin_lock_irq(&priv->lock);
+ BUG_ON(!list_empty(&priv->inflight));
+
+ list_for_each_entry_safe(buf, tmp, &priv->free, entry) {
+ list_del_init(&buf->entry);
+ spin_unlock_irq(&priv->lock);
+ data_free_buffer(dev, buf);
+ spin_lock_irq(&priv->lock);
+ }
+
+ list_for_each_entry_safe(buf, tmp, &priv->used, entry) {
+ list_del_init(&buf->entry);
+ spin_unlock_irq(&priv->lock);
+ data_free_buffer(dev, buf);
+ spin_lock_irq(&priv->lock);
+ }
+
+ priv->num_buffers = 0;
+ priv->bufsize = 0;
+
+ spin_unlock_irq(&priv->lock);
+}
+
+/**
+ * data_alloc_buffers() - allocate 1 seconds worth of data buffers
+ * @priv: the driver's private data structure
+ *
+ * Allocate enough buffers for a whole second worth of data
+ *
+ * This routine will attempt to degrade nicely by succeeding even if a full
+ * second worth of data buffers could not be allocated, as long as a minimum
+ * number were allocated. In this case, it will print a message to the kernel
+ * log.
+ *
+ * CONTEXT: user
+ * LOCKING: must hold dev->mutex
+ *
+ * Returns 0 on success, -ERRNO otherwise
+ */
+static int data_alloc_buffers(struct fpga_device *priv)
+{
+ struct device *dev = priv->dmadev;
+ struct data_buf *buf;
+ int i;
+
+ for (i = 0; i < MAX_DATA_BUFS; i++) {
+ buf = data_alloc_buffer(dev, priv->bufsize);
+ if (!buf)
+ break;
+
+ spin_lock_irq(&priv->lock);
+ list_add_tail(&buf->entry, &priv->free);
+ spin_unlock_irq(&priv->lock);
+ }
+
+ /* Make sure we allocated the minimum required number of buffers */
+ if (i < MIN_DATA_BUFS) {
+ dev_err(priv->dev, "Unable to allocate enough data buffers\n");
+ data_free_buffers(priv);
+ return -ENOMEM;
+ }
+
+ /* Warn if we are running in a degraded state, but do not fail */
+ if (i < MAX_DATA_BUFS) {
+ dev_warn(priv->dev, "Unable to allocate one second worth of "
+ "buffers, using %d buffers instead\n", i);
+ }
+
+ priv->num_buffers = i;
+ return 0;
+}
+
+/*
+ * DMA Operations Helpers
+ */
+
+/**
+ * fpga_start_addr() - get the physical address a DATA-FPGA
+ * @priv: the driver's private data structure
+ * @fpga: the DATA-FPGA number (zero based)
+ */
+static dma_addr_t fpga_start_addr(struct fpga_device *priv, unsigned int fpga)
+{
+ return priv->phys_addr + 0x400000 + (0x80000 * fpga);
+}
+
+/**
+ * fpga_block_addr() - get the physical address of a correlation data block
+ * @priv: the driver's private data structure
+ * @fpga: the DATA-FPGA number (zero based)
+ * @blknum: the correlation block number (zero based)
+ */
+static dma_addr_t fpga_block_addr(struct fpga_device *priv, unsigned int fpga,
+ unsigned int blknum)
+{
+ return fpga_start_addr(priv, fpga) + (0x10000 * (1 + blknum));
+}
+
+/**
+ * fpga_append_correlation_data() - append correlation data for DMA
+ * @priv: the driver's private data structure
+ * @slave: the Freescale DMA_SLAVE structure
+ * @fpga: the DATA-FPGA number (zero based)
+ *
+ * Add the correlation data for a single DATA FPGA to the DMA_SLAVE structure
+ *
+ * Returns 0 on success, -ERRNO otherwise
+ */
+static int fpga_append_correlation_data(struct fpga_device *priv,
+ struct fsl_dma_slave *slave,
+ unsigned int fpga)
+{
+ struct fpga_info *info = &priv->info[fpga];
+ dma_addr_t addr;
+ size_t len;
+ int i, ret;
+
+ for (i = 0; i < info->num_corl; i++) {
+ addr = fpga_block_addr(priv, fpga, i);
+ len = info->blk_size;
+ ret = fsl_dma_slave_append(slave, addr, len, GFP_KERNEL);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * data_setup_dma_slave() - create the DMA_SLAVE structure
+ * @priv: the driver's private data structure
+ *
+ * Create the DMA_SLAVE structure for transferring data from the DATA FPGA's
+ *
+ * This structure will be reused for each buffer that needs to be filled
+ * with correlation data from the DATA FPGA's
+ *
+ * Returns 0 on success, -ERRNO otherwise
+ */
+static int data_setup_dma_slave(struct fpga_device *priv)
+{
+ static const char prefix[] = "DMA_SLAVE: unable to";
+ struct fsl_dma_slave *slave;
+ dma_addr_t addr;
+ size_t len;
+ int i, ret;
+
+ /* Create the Freescale DMA_SLAVE structure */
+ slave = fsl_dma_slave_alloc(GFP_KERNEL);
+ if (!slave) {
+ dev_err(priv->dev, "%s allocate structure\n", prefix);
+ ret = -ENOMEM;
+ goto out_return;
+ }
+
+ /* Add the FPGA registers to the slave list */
+ for (i = 0; i < NUM_FPGA; i++) {
+ addr = fpga_start_addr(priv, i);
+ len = 32 * 4;
+ ret = fsl_dma_slave_append(slave, addr, len, GFP_KERNEL);
+ if (ret) {
+ dev_err(priv->dev, "%s add FPGA registers\n", prefix);
+ goto out_free_slave;
+ }
+ }
+
+ /* Add the SYS-FPGA registers to the slave list */
+ addr = SYS_FPGA_BLOCK;
+ len = 32 * 4;
+ ret = fsl_dma_slave_append(slave, addr, len, GFP_KERNEL);
+ if (ret) {
+ dev_err(priv->dev, "%s add SYS-FPGA registers\n", prefix);
+ goto out_free_slave;
+ }
+
+ /* Add the FPGA correlation data blocks to the slave list */
+ for (i = 0; i < NUM_FPGA; i++) {
+ ret = fpga_append_correlation_data(priv, slave, i);
+ if (ret) {
+ dev_err(priv->dev, "%s add correlation data\n", prefix);
+ goto out_free_slave;
+ }
+ }
+
+ /*
+ * That's everything, this slave structure can be re-used for
+ * every FPGA DATA interrupt
+ */
+ priv->slave = slave;
+ return 0;
+
+out_free_slave:
+ fsl_dma_slave_free(slave);
+out_return:
+ return ret;
+}
+
+/*
+ * FPGA Register Access Helpers
+ */
+
+static void fpga_write_reg(struct fpga_device *priv, unsigned int fpga,
+ unsigned int reg, u32 val)
+{
+ iowrite32be(val, priv->regs + 0x400000 + (fpga * 0x80000) + reg);
+}
+
+static u32 fpga_read_reg(struct fpga_device *priv, unsigned int fpga,
+ unsigned int reg)
+{
+ return ioread32be(priv->regs + 0x400000 + (fpga * 0x80000) + reg);
+}
+
+/**
+ * data_calculate_bufsize() - calculate the data buffer size required
+ * @priv: the driver's private data structure
+ *
+ * Calculate the total buffer size needed to hold a single block
+ * of correlation data
+ *
+ * CONTEXT: user
+ *
+ * Returns 0 on success, -ERRNO otherwise
+ */
+static int data_calculate_bufsize(struct fpga_device *priv)
+{
+ u32 num_corl, num_lags, num_meta, num_qcnt, blk_size;
+ u32 conf1, conf2;
+ int i;
+
+ /* Zero the total buffer size */
+ priv->bufsize = 0;
+
+ /* Read and store the configuration data for each FPGA */
+ for (i = 0; i < NUM_FPGA; i++) {
+ conf1 = fpga_read_reg(priv, i, MMAP_REG_CORL_CONF1);
+ conf2 = fpga_read_reg(priv, i, MMAP_REG_CORL_CONF2);
+
+ num_corl = (conf1 & 0x000000F0) >> 4;
+ num_lags = (conf1 & 0x000FFF00) >> 8;
+ num_meta = (conf1 & 0x7FF00000) >> 20;
+ num_qcnt = (conf2 & 0x00000FFF) >> 0;
+ blk_size = (num_lags + num_meta + num_qcnt) * 8;
+
+ priv->info[i].num_corl = num_corl;
+ priv->info[i].blk_size = blk_size;
+ priv->bufsize += num_corl * blk_size;
+
+ dev_dbg(priv->dev, "FPGA %d NUM_CORL: %d\n", i, num_corl);
+ dev_dbg(priv->dev, "FPGA %d NUM_LAGS: %d\n", i, num_lags);
+ dev_dbg(priv->dev, "FPGA %d NUM_META: %d\n", i, num_meta);
+ dev_dbg(priv->dev, "FPGA %d NUM_QCNT: %d\n", i, num_qcnt);
+ dev_dbg(priv->dev, "FPGA %d BLK_SIZE: %d\n", i, blk_size);
+ }
+
+ /* Add in the 5 FPGA register areas */
+ priv->bufsize += 5 * (32 * 4);
+ dev_dbg(priv->dev, "TOTAL BUFFER SIZE: %zu bytes\n", priv->bufsize);
+
+ return 0;
+}
+
+/*
+ * Interrupt Handling
+ */
+
+/**
+ * data_disable_interrupts() - stop the device from generating interrupts
+ * @priv: the driver's private data structure
+ *
+ * Hide interrupts by switching to GPIO interrupt source
+ *
+ * LOCKING: must hold dev->lock
+ */
+static void data_disable_interrupts(struct fpga_device *priv)
+{
+ /* hide the interrupt by switching the IRQ driver to GPIO */
+ iowrite32be(0x2F, priv->regs + SYS_IRQ_SOURCE_CTL);
+}
+
+/**
+ * data_enable_interrupts() - allow the device to generate interrupts
+ * @priv: the driver's private data structure
+ *
+ * Unhide interrupts by switching to the FPGA interrupt source. At the
+ * same time, clear the DATA-FPGA status registers.
+ *
+ * LOCKING: must hold dev->lock
+ */
+static void data_enable_interrupts(struct fpga_device *priv)
+{
+ /* clear the actual FPGA corl_done interrupt */
+ fpga_write_reg(priv, 0, MMAP_REG_STATUS, 0x0);
+ fpga_write_reg(priv, 1, MMAP_REG_STATUS, 0x0);
+ fpga_write_reg(priv, 2, MMAP_REG_STATUS, 0x0);
+ fpga_write_reg(priv, 3, MMAP_REG_STATUS, 0x0);
+
+ /* flush the writes */
+ fpga_read_reg(priv, 0, MMAP_REG_STATUS);
+
+ /* switch back to the external interrupt source */
+ iowrite32be(0x3F, priv->regs + SYS_IRQ_SOURCE_CTL);
+}
+
+/**
+ * data_dma_cb() - DMAEngine callback for DMA completion
+ * @data: the driver's private data structure
+ *
+ * Complete a DMA transfer from the DATA-FPGA's
+ *
+ * This is called via the DMA callback mechanism, and will handle moving the
+ * completed DMA transaction to the used list, and then wake any processes
+ * waiting for new data
+ *
+ * CONTEXT: any, softirq expected
+ */
+static void data_dma_cb(void *data)
+{
+ struct fpga_device *priv = data;
+ struct data_buf *buf;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ /* clear the FPGA status and re-enable interrupts */
+ data_enable_interrupts(priv);
+
+ /* If the inflight list is empty, we've got a bug */
+ BUG_ON(list_empty(&priv->inflight));
+
+ /* Grab the first buffer from the inflight list */
+ buf = list_first_entry(&priv->inflight, struct data_buf, entry);
+ list_del_init(&buf->entry);
+
+ /* Add it to the used list */
+ list_add_tail(&buf->entry, &priv->used);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ /* We've changed both the inflight and used lists, so we need
+ * to wake up any processes that are blocking for those events */
+ wake_up(&priv->wait);
+}
+
+/**
+ * data_submit_dma() - prepare and submit the required DMA to fill a buffer
+ * @priv: the driver's private data structure
+ * @buf: the data buffer
+ *
+ * Prepare and submit a DMA_SLAVE transaction for a correlation data buffer
+ *
+ * LOCKING: must hold dev->lock
+ * CONTEXT: hardirq only
+ *
+ * Returns 0 on success, -ERRNO otherwise
+ */
+static int data_submit_dma(struct fpga_device *priv, struct data_buf *buf)
+{
+ struct scatterlist *sg = buf->vb.sglist;
+ unsigned int nents = buf->vb.sglen;
+ struct dma_chan *chan = priv->chan;
+ struct dma_async_tx_descriptor *tx;
+ dma_cookie_t cookie;
+ dma_addr_t dst, src;
+
+ /*
+ * All buffers passed to this function should be ready and mapped
+ * for DMA already. Therefore, we don't need to do anything except
+ * submit it to the Freescale DMA Engine for processing
+ */
+
+ /* setup the DMA_SLAVE transaction */
+ chan->private = priv->slave;
+ tx = chan->device->device_prep_slave_sg(chan, sg, nents,
+ DMA_FROM_DEVICE, 0);
+ if (!tx) {
+ dev_err(priv->dev, "unable to prep slave DMA 1\n");
+ return -ENOMEM;
+ }
+
+ /* submit the transaction to the DMA controller */
+ cookie = tx->tx_submit(tx);
+ if (dma_submit_error(cookie)) {
+ dev_err(priv->dev, "unable to submit slave DMA 1\n");
+ return -ENOMEM;
+ }
+
+ /* Prepare the re-read of the SYS-FPGA block */
+ dst = sg_dma_address(sg) + (NUM_FPGA * 32 * 4);
+ src = SYS_FPGA_BLOCK;
+ tx = chan->device->device_prep_dma_memcpy(chan, dst, src, 32 * 4,
+ DMA_PREP_INTERRUPT);
+ if (!tx) {
+ dev_err(priv->dev, "unable to prep slave DMA 2\n");
+ return -ENOMEM;
+ }
+
+ /* Setup the callback */
+ tx->callback = data_dma_cb;
+ tx->callback_param = priv;
+
+ /* submit the transaction to the DMA controller */
+ cookie = tx->tx_submit(tx);
+ if (dma_submit_error(cookie)) {
+ dev_err(priv->dev, "unable to submit slave DMA 2\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+#define CORL_DONE 0x1
+#define CORL_ERR 0x2
+
+static irqreturn_t data_irq(int irq, void *dev_id)
+{
+ struct fpga_device *priv = dev_id;
+ struct data_buf *buf;
+ u32 status;
+ int i;
+
+ /* detect spurious interrupts via FPGA status */
+ for (i = 0; i < 4; i++) {
+ status = fpga_read_reg(priv, i, MMAP_REG_STATUS);
+ if (!(status & (CORL_DONE | CORL_ERR))) {
+ dev_err(priv->dev, "spurious irq detected (FPGA)\n");
+ return IRQ_NONE;
+ }
+ }
+
+ /* detect spurious interrupts via raw IRQ pin readback */
+ status = ioread32be(priv->regs + SYS_IRQ_INPUT_DATA);
+ if (status & IRQ_CORL_DONE) {
+ dev_err(priv->dev, "spurious irq detected (IRQ)\n");
+ return IRQ_NONE;
+ }
+
+ spin_lock(&priv->lock);
+
+ /* hide the interrupt by switching the IRQ driver to GPIO */
+ data_disable_interrupts(priv);
+
+ /* Check that we actually have a free buffer */
+ if (list_empty(&priv->free)) {
+ priv->num_dropped++;
+ data_enable_interrupts(priv);
+ goto out_unlock;
+ }
+
+ buf = list_first_entry(&priv->free, struct data_buf, entry);
+ list_del_init(&buf->entry);
+
+ /* Check the buffer size */
+ BUG_ON(buf->size != priv->bufsize);
+
+ /* Submit a DMA transfer to get the correlation data */
+ if (data_submit_dma(priv, buf)) {
+ dev_err(priv->dev, "Unable to setup DMA transfer\n");
+ list_add_tail(&buf->entry, &priv->free);
+ data_enable_interrupts(priv);
+ goto out_unlock;
+ }
+
+ /* DMA setup succeeded, GO!!! */
+ list_add_tail(&buf->entry, &priv->inflight);
+ dma_async_memcpy_issue_pending(priv->chan);
+
+out_unlock:
+ spin_unlock(&priv->lock);
+ return IRQ_HANDLED;
+}
+
+/*
+ * Realtime Device Enable Helpers
+ */
+
+/**
+ * data_device_enable() - enable the device for buffered dumping
+ * @priv: the driver's private data structure
+ *
+ * Enable the device for buffered dumping. Allocates buffers and hooks up
+ * the interrupt handler. When this finishes, data will come pouring in.
+ *
+ * LOCKING: must hold dev->mutex
+ * CONTEXT: user context only
+ *
+ * Returns 0 on success, -ERRNO otherwise
+ */
+static int data_device_enable(struct fpga_device *priv)
+{
+ u32 val;
+ int ret;
+
+ /* multiple enables are safe: they do nothing */
+ if (priv->enabled)
+ return 0;
+
+ /* check that the FPGAs are programmed */
+ val = ioread32be(priv->regs + 0x44);
+ if (!(val & (1 << 18))) {
+ dev_err(priv->dev, "DATA-FPGAs are not enabled\n");
+ return -ENODATA;
+ }
+
+ /* read the FPGAs to calculate the buffer size */
+ ret = data_calculate_bufsize(priv);
+ if (ret) {
+ dev_err(priv->dev, "unable to calculate buffer size\n");
+ goto out_error;
+ }
+
+ /* allocate the correlation data buffers */
+ ret = data_alloc_buffers(priv);
+ if (ret) {
+ dev_err(priv->dev, "unable to allocate buffers\n");
+ goto out_error;
+ }
+
+ /* allocate the DMA_SLAVE structure for correlation data */
+ ret = data_setup_dma_slave(priv);
+ if (ret) {
+ dev_err(priv->dev, "unable to setup DMA list\n");
+ goto out_error;
+ }
+
+ /* switch to the external FPGA IRQ line */
+ data_enable_interrupts(priv);
+
+ /* hookup the irq handler */
+ ret = request_irq(priv->irq, data_irq, IRQF_SHARED, drv_name, priv);
+ if (ret) {
+ dev_err(priv->dev, "unable to request IRQ handler\n");
+ goto out_free_slave;
+ }
+
+ /* success, we're enabled */
+ priv->enabled = true;
+ return 0;
+
+out_free_slave:
+ fsl_dma_slave_free(priv->slave);
+ priv->slave = NULL;
+out_error:
+ data_free_buffers(priv);
+ return ret;
+}
+
+/**
+ * data_device_disable() - disable the device for buffered dumping
+ * @priv: the driver's private data structure
+ *
+ * Disable the device for buffered dumping. Stops new DMA transactions from
+ * being generated, waits for all outstanding DMA to complete, and then frees
+ * all buffers.
+ *
+ * LOCKING: must hold dev->mutex
+ * CONTEXT: user only
+ *
+ * Returns 0 on success, -ERRNO otherwise
+ */
+static int data_device_disable(struct fpga_device *priv)
+{
+ struct list_head *list;
+ int ret;
+
+ /* allow multiple disable */
+ if (!priv->enabled)
+ return 0;
+
+ /* switch to the internal GPIO IRQ line */
+ data_disable_interrupts(priv);
+
+ /* unhook the irq handler */
+ free_irq(priv->irq, priv);
+
+ /* wait for all outstanding DMA to complete */
+ list = &priv->inflight;
+
+ spin_lock_irq(&priv->lock);
+ while (!list_empty(list)) {
+ spin_unlock_irq(&priv->lock);
+
+ ret = wait_event_interruptible(priv->wait, list_empty(list));
+ if (ret)
+ return -ERESTARTSYS;
+
+ spin_lock_irq(&priv->lock);
+ }
+ spin_unlock_irq(&priv->lock);
+
+ /* free the DMA_SLAVE structure */
+ fsl_dma_slave_free(priv->slave);
+ priv->slave = NULL;
+
+ /* free all of the buffers */
+ data_free_buffers(priv);
+ priv->enabled = false;
+ return 0;
+}
+
+/*
+ * SYSFS Attributes
+ */
+
+/*
+ * Count the number of entries in the given list
+ */
+static unsigned int list_num_entries(struct list_head *list)
+{
+ struct list_head *entry;
+ unsigned int ret = 0;
+
+ list_for_each(entry, list)
+ ret++;
+
+ return ret;
+}
+
+static ssize_t data_num_buffers_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fpga_device *priv = dev_get_drvdata(dev);
+ unsigned int num;
+
+ spin_lock_irq(&priv->lock);
+ num = priv->num_buffers;
+ spin_unlock_irq(&priv->lock);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", num);
+}
+
+static ssize_t data_bufsize_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fpga_device *priv = dev_get_drvdata(dev);
+ size_t num;
+
+ spin_lock_irq(&priv->lock);
+ num = priv->bufsize;
+ spin_unlock_irq(&priv->lock);
+
+ return snprintf(buf, PAGE_SIZE, "%zu\n", num);
+}
+
+static ssize_t data_inflight_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fpga_device *priv = dev_get_drvdata(dev);
+ unsigned int num;
+
+ spin_lock_irq(&priv->lock);
+ num = list_num_entries(&priv->inflight);
+ spin_unlock_irq(&priv->lock);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", num);
+}
+
+static ssize_t data_free_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fpga_device *priv = dev_get_drvdata(dev);
+ unsigned int num;
+
+ spin_lock_irq(&priv->lock);
+ num = list_num_entries(&priv->free);
+ spin_unlock_irq(&priv->lock);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", num);
+}
+
+static ssize_t data_used_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fpga_device *priv = dev_get_drvdata(dev);
+ unsigned int num;
+
+ spin_lock_irq(&priv->lock);
+ num = list_num_entries(&priv->used);
+ spin_unlock_irq(&priv->lock);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", num);
+}
+
+static ssize_t data_num_dropped_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fpga_device *priv = dev_get_drvdata(dev);
+ unsigned int num;
+
+ spin_lock_irq(&priv->lock);
+ num = priv->num_dropped;
+ spin_unlock_irq(&priv->lock);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", num);
+}
+
+static ssize_t data_en_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct fpga_device *priv = dev_get_drvdata(dev);
+ ssize_t count;
+
+ if (mutex_lock_interruptible(&priv->mutex))
+ return -ERESTARTSYS;
+
+ count = snprintf(buf, PAGE_SIZE, "%u\n", priv->enabled);
+ mutex_unlock(&priv->mutex);
+ return count;
+}
+
+static ssize_t data_en_set(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fpga_device *priv = dev_get_drvdata(dev);
+ unsigned long enable;
+ int ret;
+
+ ret = strict_strtoul(buf, 0, &enable);
+ if (ret) {
+ dev_err(priv->dev, "unable to parse enable input\n");
+ return -EINVAL;
+ }
+
+ if (mutex_lock_interruptible(&priv->mutex))
+ return -ERESTARTSYS;
+
+ if (enable)
+ ret = data_device_enable(priv);
+ else
+ ret = data_device_disable(priv);
+
+ if (ret) {
+ dev_err(priv->dev, "device %s failed\n",
+ enable ? "enable" : "disable");
+ count = ret;
+ goto out_unlock;
+ }
+
+out_unlock:
+ mutex_unlock(&priv->mutex);
+ return count;
+}
+
+static DEVICE_ATTR(num_buffers, S_IRUGO, data_num_buffers_show, NULL);
+static DEVICE_ATTR(buffer_size, S_IRUGO, data_bufsize_show, NULL);
+static DEVICE_ATTR(num_inflight, S_IRUGO, data_inflight_show, NULL);
+static DEVICE_ATTR(num_free, S_IRUGO, data_free_show, NULL);
+static DEVICE_ATTR(num_used, S_IRUGO, data_used_show, NULL);
+static DEVICE_ATTR(num_dropped, S_IRUGO, data_num_dropped_show, NULL);
+static DEVICE_ATTR(enable, S_IWUGO | S_IRUGO, data_en_show, data_en_set);
+
+static struct attribute *data_sysfs_attrs[] = {
+ &dev_attr_num_buffers.attr,
+ &dev_attr_buffer_size.attr,
+ &dev_attr_num_inflight.attr,
+ &dev_attr_num_free.attr,
+ &dev_attr_num_used.attr,
+ &dev_attr_num_dropped.attr,
+ &dev_attr_enable.attr,
+ NULL,
+};
+
+static const struct attribute_group rt_sysfs_attr_group = {
+ .attrs = data_sysfs_attrs,
+};
+
+/*
+ * FPGA Realtime Data Character Device
+ */
+
+static int data_open(struct inode *inode, struct file *filp)
+{
+ struct fpga_device *priv = inode_to_dev(inode);
+ struct fpga_reader *reader;
+ int ret;
+
+ /* allocate private data */
+ reader = kzalloc(sizeof(*reader), GFP_KERNEL);
+ if (!reader)
+ return -ENOMEM;
+
+ reader->priv = priv;
+ reader->buf = NULL;
+
+ filp->private_data = reader;
+ ret = nonseekable_open(inode, filp);
+ if (ret) {
+ dev_err(priv->dev, "nonseekable-open failed\n");
+ kfree(reader);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int data_release(struct inode *inode, struct file *filp)
+{
+ struct fpga_reader *reader = filp->private_data;
+ struct fpga_device *priv = reader->priv;
+
+ /* free the per-reader structure */
+ data_free_buffer(priv->dmadev, reader->buf);
+ kfree(reader);
+ return 0;
+}
+
+static ssize_t data_read(struct file *filp, char __user *ubuf, size_t count,
+ loff_t *f_pos)
+{
+ struct fpga_reader *reader = filp->private_data;
+ struct fpga_device *priv = reader->priv;
+ struct list_head *used = &priv->used;
+ struct data_buf *dbuf;
+ size_t avail;
+ void *data;
+ int ret;
+
+ /* check if we already have a partial buffer */
+ if (reader->buf) {
+ dbuf = reader->buf;
+ goto have_buffer;
+ }
+
+ spin_lock_irq(&priv->lock);
+
+ /* Block until there is at least one buffer on the used list */
+ while (list_empty(used)) {
+ spin_unlock_irq(&priv->lock);
+
+ if (filp->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+
+ if (wait_event_interruptible(priv->wait, !list_empty(used)))
+ return -ERESTARTSYS;
+
+ spin_lock_irq(&priv->lock);
+ }
+
+ /* Grab the first buffer off of the used list */
+ dbuf = list_first_entry(used, struct data_buf, entry);
+ list_del_init(&dbuf->entry);
+
+ spin_unlock_irq(&priv->lock);
+
+ /* Buffers are always mapped: unmap it */
+ data_unmap_buffer(priv->dmadev, dbuf);
+
+ /* save the buffer for later */
+ reader->buf = dbuf;
+ reader->buf_start = 0;
+
+ /* we removed a buffer from the used list: wake any waiters */
+ wake_up(&priv->wait);
+
+have_buffer:
+ /* Get the number of bytes available */
+ avail = dbuf->size - reader->buf_start;
+ data = dbuf->vb.vaddr + reader->buf_start;
+
+ /* Get the number of bytes we can transfer */
+ count = min(count, avail);
+
+ /* Copy the data to the userspace buffer */
+ if (copy_to_user(ubuf, data, count))
+ return -EFAULT;
+
+ /* Update the amount of available space */
+ avail -= count;
+
+ /* Lock against concurrent enable/disable */
+ if (mutex_lock_interruptible(&priv->mutex))
+ return -ERESTARTSYS;
+
+ /* Still some space available: save the buffer for later */
+ if (avail != 0) {
+ reader->buf_start += count;
+ reader->buf = dbuf;
+ goto out_unlock;
+ }
+
+ /*
+ * No space is available in this buffer
+ *
+ * This is a complicated decision:
+ * - if the device is not enabled: free the buffer
+ * - if the buffer is too small: free the buffer
+ */
+ if (!priv->enabled || dbuf->size != priv->bufsize) {
+ data_free_buffer(priv->dmadev, dbuf);
+ reader->buf = NULL;
+ goto out_unlock;
+ }
+
+ /*
+ * The buffer is safe to recycle: remap it and finish
+ *
+ * If this fails, we pretend that the read never happened, and return
+ * -EFAULT to userspace. They'll retry the read again.
+ */
+ ret = data_map_buffer(priv->dmadev, dbuf);
+ if (ret) {
+ dev_err(priv->dev, "unable to remap buffer for DMA\n");
+ count = -EFAULT;
+ goto out_unlock;
+ }
+
+ /* Add the buffer back to the free list */
+ reader->buf = NULL;
+ spin_lock_irq(&priv->lock);
+ list_add_tail(&dbuf->entry, &priv->free);
+ spin_unlock_irq(&priv->lock);
+
+out_unlock:
+ mutex_unlock(&priv->mutex);
+ return count;
+}
+
+static unsigned int data_poll(struct file *filp, struct poll_table_struct *tbl)
+{
+ struct fpga_reader *reader = filp->private_data;
+ struct fpga_device *priv = reader->priv;
+ unsigned int mask = 0;
+
+ poll_wait(filp, &priv->wait, tbl);
+
+ spin_lock_irq(&priv->lock);
+
+ if (!list_empty(&priv->used))
+ mask |= POLLIN | POLLRDNORM;
+
+ spin_unlock_irq(&priv->lock);
+ return mask;
+}
+
+static int data_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ struct fpga_reader *reader = filp->private_data;
+ struct fpga_device *priv = reader->priv;
+ unsigned long offset, vsize, psize, addr;
+
+ /* VMA properties */
+ offset = vma->vm_pgoff << PAGE_SHIFT;
+ vsize = vma->vm_end - vma->vm_start;
+ psize = priv->phys_size - offset;
+ addr = (priv->phys_addr + offset) >> PAGE_SHIFT;
+
+ /* Check against the FPGA region's physical memory size */
+ if (vsize > psize) {
+ dev_err(priv->dev, "requested mmap mapping too large\n");
+ return -EINVAL;
+ }
+
+ /* IO memory (stop cacheing) */
+ vma->vm_flags |= VM_IO | VM_RESERVED;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ return io_remap_pfn_range(vma, vma->vm_start, addr, vsize,
+ vma->vm_page_prot);
+}
+
+static const struct file_operations data_fops = {
+ .owner = THIS_MODULE,
+ .open = data_open,
+ .release = data_release,
+ .read = data_read,
+ .poll = data_poll,
+ .mmap = data_mmap,
+ .llseek = no_llseek,
+};
+
+/*
+ * OpenFirmware Device Subsystem
+ */
+
+static bool dma_filter(struct dma_chan *chan, void *data)
+{
+ /*
+ * DMA Channel #0 is used for the FPGA Programmer, so ignore it
+ *
+ * This probably won't survive an unload/load cycle of the Freescale
+ * DMAEngine driver, but that won't be a problem
+ */
+ if (chan->chan_id == 0 && chan->device->dev_id == 0)
+ return false;
+
+ return true;
+}
+
+static int data_of_probe(struct platform_device *op,
+ const struct of_device_id *match)
+{
+ struct device_node *of_node = op->dev.of_node;
+ struct fpga_device *priv;
+ struct resource res;
+ dma_cap_mask_t mask;
+ int ret;
+
+ /* Allocate private data */
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ dev_err(&op->dev, "Unable to allocate device private data\n");
+ ret = -ENOMEM;
+ goto out_return;
+ }
+
+ dev_set_drvdata(&op->dev, priv);
+ priv->dmadev = &op->dev;
+
+ /* Allocate the character device */
+ ret = alloc_chrdev_region(&priv->devno, 0, 1, drv_name);
+ if (ret) {
+ dev_err(&op->dev, "Unable to allocate chardev region\n");
+ goto out_free_priv;
+ }
+
+ /* Get the physical address of the FPGA registers */
+ ret = of_address_to_resource(of_node, 0, &res);
+ if (ret) {
+ dev_err(&op->dev, "Unable to find FPGA physical address\n");
+ ret = -ENODEV;
+ goto out_unregister_chrdev_region;
+ }
+
+ priv->phys_addr = res.start;
+ priv->phys_size = resource_size(&res);
+
+ /* ioremap the registers for use */
+ priv->regs = of_iomap(of_node, 0);
+ if (!priv->regs) {
+ dev_err(&op->dev, "Unable to ioremap registers\n");
+ ret = -ENOMEM;
+ goto out_unregister_chrdev_region;
+ }
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_MEMCPY, mask);
+ dma_cap_set(DMA_INTERRUPT, mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+ /* Request a DMA channel */
+ priv->chan = dma_request_channel(mask, dma_filter, NULL);
+ if (!priv->chan) {
+ dev_err(&op->dev, "Unable to request DMA channel\n");
+ ret = -ENODEV;
+ goto out_unmap_regs;
+ }
+
+ /* Find the correct IRQ number */
+ priv->irq = irq_of_parse_and_map(of_node, 0);
+ if (priv->irq == NO_IRQ) {
+ dev_err(&op->dev, "Unable to find IRQ line\n");
+ ret = -ENODEV;
+ goto out_release_dma;
+ }
+
+ priv->dev = carma_device_create(&op->dev, priv->devno, drv_name);
+ if (IS_ERR(priv->dev)) {
+ dev_err(&op->dev, "Unable to create CARMA device\n");
+ ret = PTR_ERR(priv->dev);
+ goto out_irq_dispose_mapping;
+ }
+
+ dev_set_drvdata(priv->dev, priv);
+ cdev_init(&priv->cdev, &data_fops);
+ mutex_init(&priv->mutex);
+ spin_lock_init(&priv->lock);
+ INIT_LIST_HEAD(&priv->free);
+ INIT_LIST_HEAD(&priv->used);
+ INIT_LIST_HEAD(&priv->inflight);
+ init_waitqueue_head(&priv->wait);
+
+ /* Drive the GPIO for FPGA IRQ high (no interrupt) */
+ iowrite32be(IRQ_CORL_DONE, priv->regs + SYS_IRQ_OUTPUT_DATA);
+
+ /* Register the character device */
+ ret = cdev_add(&priv->cdev, priv->devno, 1);
+ if (ret) {
+ dev_err(&op->dev, "Unable to add character device\n");
+ goto out_destroy_carma_device;
+ }
+
+ /* Create the sysfs files */
+ ret = sysfs_create_group(&priv->dev->kobj, &rt_sysfs_attr_group);
+ if (ret) {
+ dev_err(&op->dev, "Unable to create sysfs files\n");
+ goto out_cdev_del;
+ }
+
+ dev_info(&op->dev, "CARMA FPGA Realtime Data Driver Loaded\n");
+ return 0;
+
+out_cdev_del:
+ cdev_del(&priv->cdev);
+out_destroy_carma_device:
+ carma_device_destroy(priv->devno);
+out_irq_dispose_mapping:
+ irq_dispose_mapping(priv->irq);
+out_release_dma:
+ dma_release_channel(priv->chan);
+out_unmap_regs:
+ iounmap(priv->regs);
+out_unregister_chrdev_region:
+ unregister_chrdev_region(priv->devno, 1);
+out_free_priv:
+ kfree(priv);
+out_return:
+ return ret;
+}
+
+static int data_of_remove(struct platform_device *op)
+{
+ struct fpga_device *priv = dev_get_drvdata(&op->dev);
+
+ /* make sure the IRQ line is disabled */
+ mutex_lock(&priv->mutex);
+ data_device_disable(priv);
+ mutex_unlock(&priv->mutex);
+
+ sysfs_remove_group(&priv->dev->kobj, &rt_sysfs_attr_group);
+ cdev_del(&priv->cdev);
+ carma_device_destroy(priv->devno);
+
+ irq_dispose_mapping(priv->irq);
+ dma_release_channel(priv->chan);
+ iounmap(priv->regs);
+ unregister_chrdev_region(priv->devno, 1);
+ kfree(priv);
+
+ return 0;
+}
+
+static struct of_device_id data_of_match[] = {
+ { .compatible = "carma,carma-fpga", },
+ {},
+};
+
+static struct of_platform_driver data_of_driver = {
+ .probe = data_of_probe,
+ .remove = data_of_remove,
+ .driver = {
+ .name = drv_name,
+ .of_match_table = data_of_match,
+ .owner = THIS_MODULE,
+ },
+};
+
+/*
+ * Module Init / Exit
+ */
+
+static int __init data_init(void)
+{
+ return of_register_platform_driver(&data_of_driver);
+}
+
+static void __exit data_exit(void)
+{
+ of_unregister_platform_driver(&data_of_driver);
+}
+
+MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
+MODULE_DESCRIPTION("CARMA DATA-FPGA Access Driver");
+MODULE_LICENSE("GPL");
+
+module_init(data_init);
+module_exit(data_exit);
--
1.7.1
^ permalink raw reply related
* [PATCH 3/5] fpga: add basic CARMA board support
From: Ira W. Snyder @ 2010-09-08 16:41 UTC (permalink / raw)
To: linuxppc-dev; +Cc: linux-kernel, Ira W. Snyder
In-Reply-To: <1283964082-30133-1-git-send-email-iws@ovro.caltech.edu>
This adds basic support for the system controller FPGA on the OVRO CARMA
board. This patch only adds infrastructure that will be used by later
drivers.
Signed-off-by: Ira W. Snyder <iws@ovro.caltech.edu>
---
drivers/Kconfig | 2 +
drivers/Makefile | 1 +
drivers/fpga/Kconfig | 1 +
drivers/fpga/Makefile | 1 +
drivers/fpga/carma/Kconfig | 21 ++++++++++++
drivers/fpga/carma/Makefile | 1 +
drivers/fpga/carma/carma.c | 73 +++++++++++++++++++++++++++++++++++++++++++
drivers/fpga/carma/carma.h | 22 +++++++++++++
8 files changed, 122 insertions(+), 0 deletions(-)
create mode 100644 drivers/fpga/Kconfig
create mode 100644 drivers/fpga/Makefile
create mode 100644 drivers/fpga/carma/Kconfig
create mode 100644 drivers/fpga/carma/Makefile
create mode 100644 drivers/fpga/carma/carma.c
create mode 100644 drivers/fpga/carma/carma.h
diff --git a/drivers/Kconfig b/drivers/Kconfig
index a2b902f..8945ae6 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -111,4 +111,6 @@ source "drivers/xen/Kconfig"
source "drivers/staging/Kconfig"
source "drivers/platform/Kconfig"
+
+source "drivers/fpga/Kconfig"
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index ae47344..c0b05de 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -115,3 +115,4 @@ obj-$(CONFIG_VLYNQ) += vlynq/
obj-$(CONFIG_STAGING) += staging/
obj-y += platform/
obj-y += ieee802154/
+obj-$(CONFIG_FPGA_DRIVERS) += fpga/
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
new file mode 100644
index 0000000..c85c2cc
--- /dev/null
+++ b/drivers/fpga/Kconfig
@@ -0,0 +1 @@
+source "drivers/fpga/carma/Kconfig"
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
new file mode 100644
index 0000000..409a5f9
--- /dev/null
+++ b/drivers/fpga/Makefile
@@ -0,0 +1 @@
+obj-y += carma/
diff --git a/drivers/fpga/carma/Kconfig b/drivers/fpga/carma/Kconfig
new file mode 100644
index 0000000..448885e
--- /dev/null
+++ b/drivers/fpga/carma/Kconfig
@@ -0,0 +1,21 @@
+
+menuconfig FPGA_DRIVERS
+ bool "FPGA Drivers"
+ default n
+ help
+ Say Y here to see options for devices used with custom FPGAs.
+ This option alone does not add any kernel code.
+
+ If you say N, all options in this submenu will be skipped and disabled.
+
+if FPGA_DRIVERS
+
+config CARMA
+ tristate "CARMA System Controller FPGA support"
+ depends on FSL_SOC && PPC_83xx
+ default n
+ help
+ Say Y here to include basic support for the CARMA System Controller
+ FPGA. This option allows the other more advanced drivers to be built.
+
+endif # FPGA_DRIVERS
diff --git a/drivers/fpga/carma/Makefile b/drivers/fpga/carma/Makefile
new file mode 100644
index 0000000..90d0594
--- /dev/null
+++ b/drivers/fpga/carma/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_CARMA) += carma.o
diff --git a/drivers/fpga/carma/carma.c b/drivers/fpga/carma/carma.c
new file mode 100644
index 0000000..97549d2
--- /dev/null
+++ b/drivers/fpga/carma/carma.c
@@ -0,0 +1,73 @@
+/*
+ * CARMA Board Utility Driver
+ *
+ * Copyright (c) 2009-2010 Ira W. Snyder <iws@ovro.caltech.edu>
+ *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/err.h>
+
+#include "carma.h"
+
+static struct class *carma_class;
+static const char drv_name[] = "carma";
+
+/*
+ * CARMA Device Class Functions
+ */
+
+struct device *carma_device_create(struct device *parent, dev_t devno,
+ const char *fmt, ...)
+{
+ struct device *dev;
+ va_list vargs;
+
+ va_start(vargs, fmt);
+ dev = device_create_vargs(carma_class, parent, devno, NULL, fmt, vargs);
+ va_end(vargs);
+
+ return dev;
+}
+EXPORT_SYMBOL_GPL(carma_device_create);
+
+void carma_device_destroy(dev_t devno)
+{
+ device_destroy(carma_class, devno);
+}
+EXPORT_SYMBOL_GPL(carma_device_destroy);
+
+/*
+ * Module Init / Exit
+ */
+
+static int __init carma_init(void)
+{
+ /* Register the CARMA device class */
+ carma_class = class_create(THIS_MODULE, "carma");
+ if (IS_ERR(carma_class)) {
+ pr_err("%s: unable to create CARMA class\n", drv_name);
+ return PTR_ERR(carma_class);
+ }
+
+ return 0;
+}
+
+static void __exit carma_exit(void)
+{
+ class_destroy(carma_class);
+}
+
+MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
+MODULE_DESCRIPTION("CARMA Device Class Driver");
+MODULE_LICENSE("GPL");
+
+module_init(carma_init);
+module_exit(carma_exit);
diff --git a/drivers/fpga/carma/carma.h b/drivers/fpga/carma/carma.h
new file mode 100644
index 0000000..f556dc8
--- /dev/null
+++ b/drivers/fpga/carma/carma.h
@@ -0,0 +1,22 @@
+/*
+ * CARMA Board Utilities
+ *
+ * Copyright (c) 2009-2010 Ira W. Snyder <iws@ovro.caltech.edu>
+ *
+ * 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.
+ */
+
+#ifndef CARMA_DEVICE_H
+#define CARMA_DEVICE_H
+
+#include <linux/device.h>
+
+struct device *carma_device_create(struct device *parent, dev_t devno,
+ const char *fmt, ...)
+ __attribute__((format(printf, 3, 4)));
+void carma_device_destroy(dev_t devno);
+
+#endif /* CARMA_DEVICE_H */
--
1.7.1
^ permalink raw reply related
* [PATCH 2/5] fsldma: move DMA_SLAVE support functions to the driver
From: Ira W. Snyder @ 2010-09-08 16:41 UTC (permalink / raw)
To: linuxppc-dev; +Cc: linux-kernel, Ira W. Snyder
In-Reply-To: <1283964082-30133-1-git-send-email-iws@ovro.caltech.edu>
The DMA_SLAVE support functions all existed as static inlines in the
driver specific header arch/powerpc/include/asm/fsldma.h. Move the body
of the functions to the driver itself, and EXPORT_SYMBOL_GPL() them.
At the same time, add the missing linux/list.h header.
Signed-off-by: Ira W. Snyder <iws@ovro.caltech.edu>
---
arch/powerpc/include/asm/fsldma.h | 70 +++------------------------------
drivers/dma/fsldma.c | 77 +++++++++++++++++++++++++++++++++++++
2 files changed, 83 insertions(+), 64 deletions(-)
diff --git a/arch/powerpc/include/asm/fsldma.h b/arch/powerpc/include/asm/fsldma.h
index debc5ed..34ec00b 100644
--- a/arch/powerpc/include/asm/fsldma.h
+++ b/arch/powerpc/include/asm/fsldma.h
@@ -1,7 +1,7 @@
/*
* Freescale MPC83XX / MPC85XX DMA Controller
*
- * Copyright (c) 2009 Ira W. Snyder <iws@ovro.caltech.edu>
+ * Copyright (c) 2009-2010 Ira W. Snyder <iws@ovro.caltech.edu>
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
@@ -11,6 +11,7 @@
#ifndef __ARCH_POWERPC_ASM_FSLDMA_H__
#define __ARCH_POWERPC_ASM_FSLDMA_H__
+#include <linux/list.h>
#include <linux/slab.h>
#include <linux/dmaengine.h>
@@ -69,69 +70,10 @@ struct fsl_dma_slave {
bool external_pause;
};
-/**
- * fsl_dma_slave_append - add an address/length pair to a struct fsl_dma_slave
- * @slave: the &struct fsl_dma_slave to add to
- * @address: the hardware address to add
- * @length: the length of bytes to transfer from @address
- *
- * Add a hardware address/length pair to a struct fsl_dma_slave. Returns 0 on
- * success, -ERRNO otherwise.
- */
-static inline int fsl_dma_slave_append(struct fsl_dma_slave *slave,
- dma_addr_t address, size_t length)
-{
- struct fsl_dma_hw_addr *addr;
-
- addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
- if (!addr)
- return -ENOMEM;
-
- INIT_LIST_HEAD(&addr->entry);
- addr->address = address;
- addr->length = length;
-
- list_add_tail(&addr->entry, &slave->addresses);
- return 0;
-}
-
-/**
- * fsl_dma_slave_free - free a struct fsl_dma_slave
- * @slave: the struct fsl_dma_slave to free
- *
- * Free a struct fsl_dma_slave and all associated address/length pairs
- */
-static inline void fsl_dma_slave_free(struct fsl_dma_slave *slave)
-{
- struct fsl_dma_hw_addr *addr, *tmp;
-
- if (slave) {
- list_for_each_entry_safe(addr, tmp, &slave->addresses, entry) {
- list_del(&addr->entry);
- kfree(addr);
- }
-
- kfree(slave);
- }
-}
-
-/**
- * fsl_dma_slave_alloc - allocate a struct fsl_dma_slave
- * @gfp: the flags to pass to kmalloc when allocating this structure
- *
- * Allocate a struct fsl_dma_slave for use by the DMA_SLAVE API. Returns a new
- * struct fsl_dma_slave on success, or NULL on failure.
- */
-static inline struct fsl_dma_slave *fsl_dma_slave_alloc(gfp_t gfp)
-{
- struct fsl_dma_slave *slave;
-
- slave = kzalloc(sizeof(*slave), gfp);
- if (!slave)
- return NULL;
+struct fsl_dma_slave *fsl_dma_slave_alloc(gfp_t gfp);
+void fsl_dma_slave_free(struct fsl_dma_slave *slave);
- INIT_LIST_HEAD(&slave->addresses);
- return slave;
-}
+int fsl_dma_slave_append(struct fsl_dma_slave *slave, dma_addr_t address,
+ size_t length, gfp_t gfp);
#endif /* __ARCH_POWERPC_ASM_FSLDMA_H__ */
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index cea08be..f436ca4 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -38,6 +38,83 @@
#include <asm/fsldma.h>
#include "fsldma.h"
+/*
+ * External API
+ */
+
+/**
+ * fsl_dma_slave_append - add an address/length pair to a struct fsl_dma_slave
+ * @slave: the &struct fsl_dma_slave to add to
+ * @address: the hardware address to add
+ * @length: the length of bytes to transfer from @address
+ * @gfp: the flags to pass to kmalloc when allocating memory
+ *
+ * Add a hardware address/length pair to a struct fsl_dma_slave. Returns 0 on
+ * success, -ERRNO otherwise.
+ */
+int fsl_dma_slave_append(struct fsl_dma_slave *slave, dma_addr_t address,
+ size_t length, gfp_t gfp)
+{
+ struct fsl_dma_hw_addr *addr;
+
+ addr = kzalloc(sizeof(*addr), gfp);
+ if (!addr)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&addr->entry);
+ addr->address = address;
+ addr->length = length;
+
+ list_add_tail(&addr->entry, &slave->addresses);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(fsl_dma_slave_append);
+
+/**
+ * fsl_dma_slave_free - free a struct fsl_dma_slave
+ * @slave: the struct fsl_dma_slave to free
+ *
+ * Free a struct fsl_dma_slave and all associated address/length pairs
+ */
+void fsl_dma_slave_free(struct fsl_dma_slave *slave)
+{
+ struct fsl_dma_hw_addr *addr, *tmp;
+
+ if (slave) {
+ list_for_each_entry_safe(addr, tmp, &slave->addresses, entry) {
+ list_del(&addr->entry);
+ kfree(addr);
+ }
+
+ kfree(slave);
+ }
+}
+EXPORT_SYMBOL_GPL(fsl_dma_slave_free);
+
+/**
+ * fsl_dma_slave_alloc - allocate a struct fsl_dma_slave
+ * @gfp: the flags to pass to kmalloc when allocating this structure
+ *
+ * Allocate a struct fsl_dma_slave for use by the DMA_SLAVE API. Returns a new
+ * struct fsl_dma_slave on success, or NULL on failure.
+ */
+struct fsl_dma_slave *fsl_dma_slave_alloc(gfp_t gfp)
+{
+ struct fsl_dma_slave *slave;
+
+ slave = kzalloc(sizeof(*slave), gfp);
+ if (!slave)
+ return NULL;
+
+ INIT_LIST_HEAD(&slave->addresses);
+ return slave;
+}
+EXPORT_SYMBOL_GPL(fsl_dma_slave_alloc);
+
+/*
+ * Driver Code
+ */
+
static void dma_init(struct fsldma_chan *chan)
{
/* Reset the channel */
--
1.7.1
^ permalink raw reply related
* [PATCH 1/5] fsldma: fix missing header include
From: Ira W. Snyder @ 2010-09-08 16:41 UTC (permalink / raw)
To: linuxppc-dev; +Cc: linux-kernel, Ira W. Snyder
In-Reply-To: <1283964082-30133-1-git-send-email-iws@ovro.caltech.edu>
The slab.h header is required to use the kmalloc() family of functions.
Due to recent kernel changes, this header must be directly included by
code that calls into the memory allocator.
Signed-off-by: Ira W. Snyder <iws@ovro.caltech.edu>
---
arch/powerpc/include/asm/fsldma.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/include/asm/fsldma.h b/arch/powerpc/include/asm/fsldma.h
index a67aeed..debc5ed 100644
--- a/arch/powerpc/include/asm/fsldma.h
+++ b/arch/powerpc/include/asm/fsldma.h
@@ -11,6 +11,7 @@
#ifndef __ARCH_POWERPC_ASM_FSLDMA_H__
#define __ARCH_POWERPC_ASM_FSLDMA_H__
+#include <linux/slab.h>
#include <linux/dmaengine.h>
/*
--
1.7.1
^ permalink raw reply related
* [PATCH RFCv2 0/5] CARMA Board Support
From: Ira W. Snyder @ 2010-09-08 16:41 UTC (permalink / raw)
To: linuxppc-dev; +Cc: linux-kernel, Ira W. Snyder
Hello everyone,
This is the second posting of these drivers, taking into account comments
from the RFCv1 post. Thanks to all that contributed.
The changes:
- change comments to kerneldoc format
- Kconfig improvements
- use the videobuf_dma_sg API in the programmer
- updates for Freescale DMAEngine DMA_SLAVE API changes
In a seperate thread, AKPM asked for some changes to the Freescale
DMAEngine driver. They are already part of -mm, and do not need review. To
make testing easier, I have included the changes as the first two patches
in this series. If you are using -mm, please ignore them.
Information about the CARMA board:
The CARMA board is essentially an MPC8349EA MDS reference design with a
1GHz ADC and 4 high powered data processing FPGAs connected to the local
bus. It is all packed into a compact PCI form factor. It is used at the
Owens Valley Radio Observatory as the main component in the correlator
system.
For more information, see this webpage, maintained by the board's hardware
engineer: http://www.mmarray.org/~dwh/carma_board/index.html
These drivers are the necessary pieces to get the data processing FPGAs
working and producing data. Despite the fact that the hardware is custom
and we are the only users, I'd still like to get the drivers upstream.
Several people have suggested that this is possible.
Some further patches will be forthcoming. I have a driver for the LED
subsystem and the PPS subsystem. The LED register layout is expected to
change soon, so I won't post the driver until that is finished. The PPS
driver will be posted seperately from this patch series; it is very
generic.
Thanks for any review and comments you can offer!
Ira
Ira W. Snyder (5):
fsldma: fix missing header include
fsldma: move DMA_SLAVE support functions to the driver
fpga: add basic CARMA board support
fpga: add CARMA DATA-FPGA Access Driver
fpga: add CARMA DATA-FPGA Programmer support
arch/powerpc/include/asm/fsldma.h | 71 +--
drivers/Kconfig | 2 +
drivers/Makefile | 1 +
drivers/dma/fsldma.c | 77 ++
drivers/fpga/Kconfig | 1 +
drivers/fpga/Makefile | 1 +
drivers/fpga/carma/Kconfig | 38 +
drivers/fpga/carma/Makefile | 3 +
drivers/fpga/carma/carma-fpga-program.c | 1023 +++++++++++++++++++++
drivers/fpga/carma/carma-fpga.c | 1471 +++++++++++++++++++++++++++++++
drivers/fpga/carma/carma.c | 73 ++
drivers/fpga/carma/carma.h | 22 +
12 files changed, 2719 insertions(+), 64 deletions(-)
create mode 100644 drivers/fpga/Kconfig
create mode 100644 drivers/fpga/Makefile
create mode 100644 drivers/fpga/carma/Kconfig
create mode 100644 drivers/fpga/carma/Makefile
create mode 100644 drivers/fpga/carma/carma-fpga-program.c
create mode 100644 drivers/fpga/carma/carma-fpga.c
create mode 100644 drivers/fpga/carma/carma.c
create mode 100644 drivers/fpga/carma/carma.h
^ permalink raw reply
* Re: pci_request_regions() failure
From: Ravi Gupta @ 2010-09-08 9:29 UTC (permalink / raw)
To: tiejun.chen; +Cc: linuxppc-dev
In-Reply-To: <4C8604E1.4080908@windriver.com>
[-- Attachment #1: Type: text/plain, Size: 18787 bytes --]
Hi Tiejun,
Thanks for the reply.
Your PCI device should be one virtual device so I think the above should be
> as
> we understood. You know 0x00000000 ~ 0x00003ffff should not be allowed to
> reserved.
>
Can you explain a little more that what do you mean by "Your PCI device
should be one virtual device"?
> I think you should do the following sequence in the probe function of your
> PCI
> driver.
>
> 1. pci_enable_device(pdev);
> 2. pci_request_regions(pdev, DRV_NAME);
> 3. pci_set_master(pdev);
> ......
>
> Okay, I have changed my drive code to follow this sequence, but still no
success. It fails with the same errors as before.
# insmod ./pci_skel.ko
PCI driver: Init function
PCI driver: Probe function
pci_skel 0001:02:00.0: device not available (can't reserve [mem
0x00000000-0x0003ffff])
Unable to Enable PCI device:-22
pci_skel: probe of 0001:02:00.0 failed with error -22
Looks we need some pci_fixup to modify them. Firstly I think you'd better
> 'zero'
> all BARs of your PCI device on the function, pci_scan_device, on the file,
> drivers/pci/probe.c. On there you can dedicate that once your device is
> probed.
> Please check the each BAR's value again after the above fix.
>
>
Okay, I have set the BARs with all zeros in the pci_scan_device() function.
Below is the diff of the changes done by me.
--- /data/sources/linux-2.6.35/drivers/pci/probe.c 2010-08-02
03:41:14.000000000 +0530
+++ probe.c 2010-09-08 14:45:40.000000000 +0530
@@ -1172,6 +1172,45 @@ static struct pci_dev *pci_scan_device(s
}
}
+ printk(KERN_WARNING "pci : vendor id = 0x%x\n", l & 0xffff);
+ if ((l & 0xffff) == 0x1204) {
+ /* zero's all BAR registers */
+ printk(KERN_WARNING "pci %04x:%02x:%02x.%d: trying to set all zeros in "
+ "BARs\n", pci_domain_nr(bus),
+ bus->number, PCI_SLOT(devfn),
+ PCI_FUNC(devfn));
+
+ if(pci_bus_write_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, 0x0) ||
+ pci_bus_write_config_dword(bus, devfn, PCI_BASE_ADDRESS_1, 0x0) ||
+ pci_bus_write_config_dword(bus, devfn, PCI_BASE_ADDRESS_2, 0x0) ||
+ pci_bus_write_config_dword(bus, devfn, PCI_BASE_ADDRESS_3, 0x0) ||
+ pci_bus_write_config_dword(bus, devfn, PCI_BASE_ADDRESS_4, 0x0) ||
+ pci_bus_write_config_dword(bus, devfn, PCI_BASE_ADDRESS_5, 0x0)) {
+
+ printk(KERN_WARNING "pci %04x:%02x:%02x.%d: failed to reset bits"
+ "of BARs\n", pci_domain_nr(bus),
+ bus->number, PCI_SLOT(devfn),
+ PCI_FUNC(devfn));
+ return NULL;
+ }
+ }
+
dev = alloc_pci_dev();
if (!dev)
return NULL;
The difference I have seen in the dmesg is that the following two messages
are not coming now.
PCI: Cannot allocate resource region 0 of device 0001:02:00.0, will remap
PCI: Cannot allocate resource region 1 of device 0001:02:00.0, will remap
But my driver is still fails with the same error as before. I am attaching
the new dmesg log.
Dmesg with all BARs set to zero
================================================================
Using MPC837x RDB/WLAN machine description
Initializing cgroup subsys cpuset
Initializing cgroup subsys cpu
Linux version 2.6.35 (okapi@okapi) (gcc version 4.2.3 (Sourcery G++ Lite
4.2-171)) #28 Wed Sep 8 13:20:27 IST 2010
Found initrd at 0xcf46c000:0xcf7b05b7
Found legacy serial port 0 for /immr@e0000000/serial@4500
mem=e0004500, taddr=e0004500, irq=0, clk=400000002, speed=0
Found legacy serial port 1 for /immr@e0000000/serial@4600
mem=e0004600, taddr=e0004600, irq=0, clk=400000002, speed=0
bootconsole [udbg0] enabled
Found FSL PCI host bridge at 0x00000000e0008500. Firmware bus number: 0->0
PCI host bridge /pci@e0008500 (primary) ranges:
MEM 0x0000000090000000..0x000000009fffffff -> 0x0000000090000000
MEM 0x0000000080000000..0x000000008fffffff -> 0x0000000080000000 Prefetch
IO 0x00000000e0300000..0x00000000e03fffff -> 0x0000000000000000
No pci config register base in dev tree, using default
Found FSL PCI host bridge at 0x00000000e0009000. Firmware bus number: 0->255
PCI host bridge /pcie@e0009000 ranges:
MEM 0x00000000a8000000..0x00000000b7ffffff -> 0x00000000a8000000
IO 0x00000000b8000000..0x00000000b87fffff -> 0x0000000000000000
No pci config register base in dev tree, using default
Found FSL PCI host bridge at 0x00000000e000a000. Firmware bus number: 0->255
PCI host bridge /pcie@e000a000 ranges:
MEM 0x00000000c8000000..0x00000000d7ffffff -> 0x00000000c8000000
IO 0x00000000d8000000..0x00000000d87fffff -> 0x0000000000000000
Top of RAM: 0x10000000, Total RAM: 0x10000000
Memory hole size: 0MB
Zone PFN ranges:
DMA 0x00000000 -> 0x00010000
Normal empty
HighMem empty
Movable zone start PFN for each node
early_node_map[1] active PFN ranges
0: 0x00000000 -> 0x00010000
On node 0 totalpages: 65536
free_area_init_node: node 0, pgdat c04265e8, node_mem_map c0800000
DMA zone: 512 pages used for memmap
DMA zone: 0 pages reserved
DMA zone: 65024 pages, LIFO batch:15
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 65024
Kernel command line: root=/dev/ram ramdisk_size=120000 rw ip=10.20.50.230:10
.20.50.70:10.20.50.50:255.255.0.0:PowerQUICC:eth0:off console=ttyS0,115200
mtdparts=nand:4m(kernel),-(jffs2)
PID hash table entries: 1024 (order: 0, 4096 bytes)
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
High memory: 0k
Memory: 249972k/262144k available (4064k kernel code, 12172k reserved, 244k
data, 2187k bss, 188k init)
Kernel virtual memory layout:
* 0xfffcf000..0xfffff000 : fixmap
* 0xff800000..0xffc00000 : highmem PTEs
* 0xfe6f7000..0xff800000 : early ioremap
* 0xd1000000..0xfe6f7000 : vmalloc & ioremap
Hierarchical RCU implementation.
RCU-based detection of stalled CPUs is disabled.
Verbose stalled-CPUs detection is disabled.
NR_IRQS:512
IPIC (128 IRQ sources) at d1000700
time_init: decrementer frequency = 100.000000 MHz
time_init: processor frequency = 800.000004 MHz
clocksource: timebase mult[2800000] shift[22] registered
clockevent: decrementer mult[19999999] shift[32] cpu[0]
Console: colour dummy device 80x25
pid_max: default: 32768 minimum: 301
Security Framework initialized
SELinux: Disabled at boot.
Mount-cache hash table entries: 512
Initializing cgroup subsys ns
Initializing cgroup subsys cpuacct
Initializing cgroup subsys devices
NET: Registered protocol family 16
irq: irq 38 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 38
__irq_set_trigger: setting type, irq = 38, flags = 8
ipic_set_irq_type function, with virq = 38, flow = 8
irq: irq 74 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 74
__irq_set_trigger: setting type, irq = 74, flags = 8
ipic_set_irq_type function, with virq = 74, flow = 8
irq: irq 75 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 75
__irq_set_trigger: setting type, irq = 75, flags = 8
ipic_set_irq_type function, with virq = 75, flow = 8
PCI: Probing PCI hardware
PCI: Scanning PHB /pci@e0008500
PCI: PHB IO resource = 0000000000000000-00000000000fffff [100]
PCI: PHB MEM resource 0 = 0000000090000000-000000009fffffff [200]
PCI: PHB MEM resource 1 = 0000000080000000-000000008fffffff [2200]
PCI: PHB MEM offset = 0000000000000000
PCI: PHB IO offset = 00000000
probe mode: 0
pci_bus 0000:00: scanning bus
pci : vendor id = 0x1957
pci 0000:00:00.0: found [1957:00c6] class 000b20 header type 00
pci 0000:00:00.0: reg 10: [mem 0x00000000-0x000fffff]
pci 0000:00:00.0: reg 18: [mem 0x00000000-0x0fffffff 64bit pref]
pci 0000:00:00.0: calling fixup_hide_host_resource_fsl+0x0/0x58
pci 0000:00:00.0: calling pcibios_fixup_resources+0x0/0x180
pci 0000:00:00.0: calling quirk_fsl_pcie_header+0x0/0x48
pci 0000:00:00.0: calling quirk_resource_alignment+0x0/0x1c0
pci 0000:00:00.0: supports D1 D2
pci 0000:00:00.0: PME# supported from D0 D1 D2 D3hot
pci 0000:00:00.0: PME# disabled
pci_bus 0000:00: fixups for bus
PCI: Fixup bus devices 0 (PHB)
PCI: Try to map irq for 0000:00:00.0...
pci_bus 0000:00: bus scan returning with max=00
PCI: Scanning PHB /pcie@e0009000
PCI: PHB IO resource = 00000000ff7fe000-00000000ffffdfff [100]
PCI: PHB MEM resource 0 = 00000000a8000000-00000000b7ffffff [200]
PCI: PHB MEM offset = 0000000000000000
PCI: PHB IO offset = ff7fe000
probe mode: 0
pci_bus 0001:01: scanning bus
pci : vendor id = 0x1957
pci 0001:01:00.0: found [1957:00c6] class 000b20 header type 01
pci 0001:01:00.0: ignoring class b20 (doesn't match header type 01)
pci 0001:01:00.0: calling fixup_hide_host_resource_fsl+0x0/0x58
pci 0001:01:00.0: calling pcibios_fixup_resources+0x0/0x180
pci 0001:01:00.0: calling quirk_fsl_pcie_header+0x0/0x48
pci 0001:01:00.0: calling quirk_resource_alignment+0x0/0x1c0
pci 0001:01:00.0: supports D1 D2
pci 0001:01:00.0: PME# supported from D0 D1 D2 D3hot
pci 0001:01:00.0: PME# disabled
pci_bus 0001:01: fixups for bus
PCI: Fixup bus devices 1 (PHB)
PCI: Try to map irq for 0001:01:00.0...
pci 0001:01:00.0: scanning [bus 01-ff] behind bridge, pass 0
pci 0001:01:00.0: bus configuration invalid, reconfiguring
pci 0001:01:00.0: scanning [bus 00-00] behind bridge, pass 1
pci_bus 0001:02: scanning bus
pci : vendor id = 0x1204
pci 0001:02:00.0: trying to set all zeros in BARs
pci 0001:02:00.0: found [1204:e250] class 000000 header type 00
pci 0001:02:00.0: reg 10: [mem 0x00000000-0x0003ffff]
pci 0001:02:00.0: reg 14: [mem 0x00000000-0x0003ffff]
pci 0001:02:00.0: calling pcibios_fixup_resources+0x0/0x180
PCI:0001:02:00.0 Resource 0 0000000000000000-000000000003ffff [40200] is
unassigned
PCI:0001:02:00.0 Resource 1 0000000000000000-000000000003ffff [40200] is
unassigned
pci 0001:02:00.0: calling quirk_resource_alignment+0x0/0x1c0
pci_bus 0001:02: fixups for bus
pci 0001:01:00.0: PCI bridge to [bus 02-ff]
pci 0001:01:00.0: bridge window [io 0x0000-0x0000] (disabled)
pci 0001:01:00.0: bridge window [mem 0x00000000-0x000fffff] (disabled)
pci 0001:01:00.0: bridge window [mem 0x00000000-0x000fffff pref]
(disabled)
PCI: Fixup bus devices 2 (0001:01:00.0)
PCI: Try to map irq for 0001:02:00.0...
Got one, spec 2 cells (0x00000001 0x00000008...) on /immr@e0000000
/interrupt-controller@700
irq: irq 1 on host /immr@e0000000/interrupt-controller@700 mapped to virtual
irq 16
__irq_set_trigger: setting type, irq = 16, flags = 8
ipic_set_irq_type function, with virq = 16, flow = 8
Mapped to linux irq 16
pci_bus 0001:02: bus scan returning with max=02
pci_bus 0001:01: bus scan returning with max=02
PCI: Scanning PHB /pcie@e000a000
PCI: PHB IO resource = 00000000feffc000-00000000ff7fbfff [100]
PCI: PHB MEM resource 0 = 00000000c8000000-00000000d7ffffff [200]
PCI: PHB MEM offset = 0000000000000000
PCI: PHB IO offset = feffc000
probe mode: 0
pci_bus 0002:03: scanning bus
pci_bus 0002:03: fixups for bus
PCI: Fixup bus devices 3 (PHB)
pci_bus 0002:03: bus scan returning with max=03
PCI->OF bus map:
0 -> 0
1 -> 0
3 -> 0
PCI: Allocating bus resources for 0000:00...
PCI: PHB (bus 0) bridge rsrc 0: 0000000000000000-00000000000fffff [0x100],
parent c03fe5a0 (PCI IO)
PCI: PHB (bus 0) bridge rsrc 1: 0000000090000000-000000009fffffff [0x200],
parent c03fe584 (PCI mem)
PCI: PHB (bus 0) bridge rsrc 2: 0000000080000000-000000008fffffff [0x2200],
parent c03fe584 (PCI mem)
PCI: Allocating bus resources for 0001:01...
PCI: PHB (bus 1) bridge rsrc 0: 00000000ff7fe000-00000000ffffdfff [0x100],
parent c03fe5a0 (PCI IO)
PCI: PHB (bus 1) bridge rsrc 1: 00000000a8000000-00000000b7ffffff [0x200],
parent c03fe584 (PCI mem)
PCI: Allocating bus resources for 0001:02...
PCI: Allocating bus resources for 0002:03...
PCI: PHB (bus 3) bridge rsrc 0: 00000000feffc000-00000000ff7fbfff [0x100],
parent c03fe5a0 (PCI IO)
PCI: PHB (bus 3) bridge rsrc 1: 00000000c8000000-00000000d7ffffff [0x200],
parent c03fe584 (PCI mem)
Reserving legacy ranges for domain 0000
Candidate legacy IO: [io 0x0000-0x0fff]
hose mem offset: 0000000000000000
hose mem res: [mem 0x90000000-0x9fffffff]
hose mem res: [mem 0x80000000-0x8fffffff pref]
Reserving legacy ranges for domain 0001
Candidate legacy IO: [io 0xff7fe000-0xff7fefff]
hose mem offset: 0000000000000000
hose mem res: [mem 0xa8000000-0xb7ffffff]
Reserving legacy ranges for domain 0002
Candidate legacy IO: [io 0xfeffc000-0xfeffcfff]
hose mem offset: 0000000000000000
hose mem res: [mem 0xc8000000-0xd7ffffff]
PCI: Assigning unassigned resources...
pci 0001:01:00.0: BAR 8: assigned [mem 0xa8000000-0xa80fffff]
pci 0001:01:00.0: PCI bridge to [bus 02-02]
pci 0001:01:00.0: bridge window [io disabled]
pci 0001:01:00.0: bridge window [mem 0xa8000000-0xa80fffff]
pci 0001:01:00.0: bridge window [mem pref disabled]
pci_bus 0000:00: resource 0 [io 0x0000-0xfffff]
pci_bus 0000:00: resource 1 [mem 0x90000000-0x9fffffff]
pci_bus 0000:00: resource 2 [mem 0x80000000-0x8fffffff pref]
pci_bus 0001:01: resource 0 [io 0xff7fe000-0xffffdfff]
pci_bus 0001:01: resource 1 [mem 0xa8000000-0xb7ffffff]
pci_bus 0001:02: resource 1 [mem 0xa8000000-0xa80fffff]
pci_bus 0002:03: resource 0 [io 0xfeffc000-0xff7fbfff]
pci_bus 0002:03: resource 1 [mem 0xc8000000-0xd7ffffff]
Registering qe_ic with sysfs...
Registering ipic with sysfs...
bio: create slab <bio-0> at 0
vgaarb: loaded
SCSI subsystem initialized
Switching to clocksource timebase
NET: Registered protocol family 2
IP route cache hash table entries: 2048 (order: 1, 8192 bytes)
TCP established hash table entries: 8192 (order: 4, 65536 bytes)
TCP bind hash table entries: 8192 (order: 3, 32768 bytes)
TCP: Hash tables configured (established 8192 bind 8192)
TCP reno registered
UDP hash table entries: 256 (order: 0, 4096 bytes)
UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
NET: Registered protocol family 1
pci 0000:00:00.0: calling quirk_cardbus_legacy+0x0/0x44
pci 0000:00:00.0: calling quirk_usb_early_handoff+0x0/0x740
pci 0001:01:00.0: calling quirk_cardbus_legacy+0x0/0x44
pci 0001:01:00.0: calling quirk_usb_early_handoff+0x0/0x740
pci 0001:02:00.0: calling quirk_cardbus_legacy+0x0/0x44
pci 0001:02:00.0: calling quirk_usb_early_handoff+0x0/0x740
PCI: CLS 32 bytes, default 32
Trying to unpack rootfs image as initramfs...
rootfs image is not initramfs (no cpio magic); looks like an initrd
Freeing initrd memory: 3345k freed
irq: irq 9 on host /immr@e0000000/interrupt-controller@700 mapped to virtual
irq 17
__irq_set_trigger: setting type, irq = 17, flags = 8
ipic_set_irq_type function, with virq = 17, flow = 8
irq: irq 10 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 18
__irq_set_trigger: setting type, irq = 18, flags = 8
ipic_set_irq_type function, with virq = 18, flow = 8
irq: irq 80 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 80
__irq_set_trigger: setting type, irq = 80, flags = 8
ipic_set_irq_type function, with virq = 80, flow = 8
audit: initializing netlink socket (disabled)
type=2000 audit(0.212:1): initialized
JFFS2 version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
SGI XFS with security attributes, large block/inode numbers, no debug
enabled
msgmni has been set to 494
alg: No test for cipher_null (cipher_null-generic)
alg: No test for ecb(cipher_null) (ecb-cipher_null)
alg: No test for digest_null (digest_null-generic)
alg: No test for compress_null (compress_null-generic)
alg: No test for stdrng (krng)
Block layer SCSI generic (bsg) driver version 0.4 loaded (major 253)
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
serial8250.0: ttyS0 at MMIO 0xe0004500 (irq = 17) is a 16550A
console [ttyS0] enabled, bootconsole disabled
serial8250.0: ttyS1 at MMIO 0xe0004600 (irq = 18) is a 16550A
brd: module loaded
of_mpc8xxx_spi_probe function called.
irq: irq 16 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 19
__irq_set_trigger: setting type, irq = 19, flags = 8
ipic_set_irq_type function, with virq = 19, flow = 8
mpc8xxx_spi_probe function called.
mpc8xxx_spi e0007000.spi: at 0xd1078000 (irq = 19), CPU mode
irq: irq 32 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 32
__irq_set_trigger: setting type, irq = 32, flags = 8
ipic_set_irq_type function, with virq = 32, flow = 8
irq: irq 33 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 33
__irq_set_trigger: setting type, irq = 33, flags = 8
ipic_set_irq_type function, with virq = 33, flow = 8
irq: irq 34 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 34
__irq_set_trigger: setting type, irq = 34, flags = 8
ipic_set_irq_type function, with virq = 34, flow = 8
eth0: Gianfar Ethernet Controller Version 1.2, 04:00:00:00:00:0a
eth0: Running with NAPI enabled
eth0: RX BD ring size for Q[0]: 256
eth0: TX BD ring size for Q[0]: 256
irq: irq 35 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 35
__irq_set_trigger: setting type, irq = 35, flags = 8
ipic_set_irq_type function, with virq = 35, flow = 8
irq: irq 36 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 36
__irq_set_trigger: setting type, irq = 36, flags = 8
ipic_set_irq_type function, with virq = 36, flow = 8
irq: irq 37 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 37
__irq_set_trigger: setting type, irq = 37, flags = 8
ipic_set_irq_type function, with virq = 37, flow = 8
eth1: Gianfar Ethernet Controller Version 1.2, 00:00:00:00:00:00
eth1: Running with NAPI enabled
eth1: RX BD ring size for Q[0]: 256
eth1: TX BD ring size for Q[0]: 256
ucc_geth: QE UCC Gigabit Ethernet Controller
Freescale PowerQUICC MII Bus: probed
irq: irq 17 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 20
__irq_set_trigger: setting type, irq = 20, flags = 8
ipic_set_irq_type function, with virq = 20, flow = 8
Freescale PowerQUICC MII Bus: probed
mice: PS/2 mouse device common for all mice
Skipping unavailable LED gpio -19 (pwr)
Skipping unavailable LED gpio -19 (hdd)
TCP cubic registered
NET: Registered protocol family 17
registered taskstats version 1
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
RAMDISK: gzip image found at block 0
VFS: Mounted root (ext2 filesystem) on device 1:0.
Freeing unused kernel memory: 188k init
PHY: mdio@e0024520:02 - Link is Up - 10/Half
================================================================
Regards,
Ravi
[-- Attachment #2: Type: text/html, Size: 20382 bytes --]
^ permalink raw reply
* Re: [RFC] arch/powerpc: Remove duplicate/redundant Altivec entries
From: Paul Mackerras @ 2010-09-08 1:59 UTC (permalink / raw)
To: Matthew McClintock; +Cc: linuxppc-dev
In-Reply-To: <1283885815-11175-1-git-send-email-msm@freescale.com>
On Tue, Sep 07, 2010 at 01:56:55PM -0500, Matthew McClintock wrote:
> In lieu of having multiple similiar lines, we can just have one
> generic cpu-as line for CONFIG_ALTIVEC
>
> ---
> Was hoping to get comments about this change and if anyone sees any potential
> problems?
I have a memory that we can get some altivec instructions even with
CONFIG_ALTIVEC = n, though presumably they never get executed. We
would have to check that before applying your patch.
Paul.
^ permalink raw reply
* Re: kexec on ppc64
From: Michael Neuling @ 2010-09-07 23:49 UTC (permalink / raw)
To: Matthew McClintock; +Cc: linuxppc-dev, kexec
In-Reply-To: <0D324CAF-2A5D-4363-9000-7EB48179C11C@freescale.com>
> I'm trying to determine how kexec'ing works on 64 bit powerpc. When
> allocating a region for the kexec'ed kernel is it ever the same as the
> currently running kernel or do you always boot the kexec'ed kernel
> from a different memory region? I understand that a crash kernel will
> be in a different region, however I was hoping to confirm the behavior
> for a normal "kexec -e".
The kernel will be loaded at a non zero address, but it will copy itself
to zero before it starts running.
Mikey
^ permalink raw reply
* Re: [PATCH 0/8] sdhci: Move real work out of an atomic context
From: Andrew Morton @ 2010-09-07 22:38 UTC (permalink / raw)
To: Anton Vorontsov
Cc: Matt Fleming, Albert Herranz, linux-mmc, linux-kernel,
linuxppc-dev, Ben Dooks, Pierre Ossman
In-Reply-To: <20100714130728.GA27339@oksana.dev.rtsoft.ru>
On Wed, 14 Jul 2010 17:07:28 +0400
Anton Vorontsov <avorontsov@mvista.com> wrote:
> Hi all,
>
> Currently the sdhci driver does everything in the atomic context.
> And what is worse, PIO transfers are made from the IRQ handler.
>
> This causes huge latencies (up to 120 ms). On some P2020 SOCs,
> DMA and card detection is broken, which means that kernel polls
> for the card via PIO transfers every second. Needless to say
> that this is quite bad.
>
> So, this patch set reworks sdhci code to avoid atomic context,
> almost completely. We only do two device memory operations
> in the atomic context, and all the rest is threaded.
>
> I noticed no throughput drop neither with PIO transfers nor
> with DMA (tested on MPC8569E CPU), while latencies should be
> greatly improved.
>
This patchset isn't causing any problems yet, but may do so in the
future and will impact the validity of any testing. It seems to be
kind of stuck. Should I drop it all?
^ permalink raw reply
* Re: drivers/ata/sata_dwc_460ex.c fails to build
From: Wolfgang Denk @ 2010-09-07 21:00 UTC (permalink / raw)
To: Rupjyoti Sarmah; +Cc: linuxppc-dev, Prodyut Hazarika, Mark Miesfeld
In-Reply-To: <5205dc59ca0e0fd65e50d80eeff60d01@mail.gmail.com>
Dear Rupjyoti Sarmah,
In message <5205dc59ca0e0fd65e50d80eeff60d01@mail.gmail.com> you wrote:
>
> The current mainline 2.6.36-rc3 does not report any error while building
> the SATA driver.
It reports a lot of warnings, though:
-> git describe
v2.6.36-rc3
In file included from drivers/ata/sata_dwc_460ex.c:38:
drivers/ata/libata.h:31:1: warning: this is the location of the previous definition
drivers/ata/sata_dwc_460ex.c:44:1: warning: "DRV_VERSION" redefined
drivers/ata/libata.h:32:1: warning: this is the location of the previous definition
drivers/ata/sata_dwc_460ex.c: In function 'sata_dwc_exec_command_by_tag':
drivers/ata/sata_dwc_460ex.c:1356: warning: passing argument 1 of 'ata_get_cmd_descript' makes integer from pointer without a cast
drivers/ata/sata_dwc_460ex.c: In function 'sata_dwc_qc_issue':
drivers/ata/sata_dwc_460ex.c:1476: warning: 'err' is used uninitialized in this function
drivers/ata/sata_dwc_460ex.c:1465: note: 'err' was declared here
drivers/scsi/constants.c: In function 'scsi_print_sense':
drivers/scsi/constants.c:1407: warning: zero-length printf format string
drivers/scsi/constants.c:1413: warning: zero-length printf format string
drivers/scsi/constants.c: In function 'scsi_print_result':
drivers/scsi/constants.c:1456: warning: zero-length printf format string
drivers/scsi/sd.c: In function 'sd_print_sense_hdr':
drivers/scsi/sd.c:2628: warning: zero-length printf format string
drivers/scsi/sd.c:2630: warning: zero-length printf format string
drivers/scsi/sd.c: In function 'sd_print_result':
drivers/scsi/sd.c:2636: warning: zero-length printf format string
And the ``'err' is used uninitialized'' warning is indeed a valid one.
Best regards,
Wolfgang Denk
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
What is mind? No matter. What is matter? Never mind.
-- Thomas Hewitt Key, 1799-1875
^ permalink raw reply
* Re: [PATCH] mpc8308_p1m: support for MPC8308 P1M board
From: Scott Wood @ 2010-09-07 20:28 UTC (permalink / raw)
To: Ilya Yanok; +Cc: vlad, linuxppc-dev, wd, dzu
In-Reply-To: <1283854143-2299-1-git-send-email-yanok@emcraft.com>
On Tue, 7 Sep 2010 12:09:03 +0200
Ilya Yanok <yanok@emcraft.com> wrote:
> + compatible = "mpc8308_p1m";
This needs a vendor prefix.
> + i2c0@3000 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + cell-index = <0>;
> + compatible = "fsl-i2c";
> + reg = <0x3000 0x100>;
> + interrupts = <14 0x8>;
> + interrupt-parent = <&ipic>;
> + dfsrr;
> + fram@50 {
> + compatible = "ramtron,24c64";
> + reg = <0x50>;
> + };
> + };
> +
> + i2c1@3100 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + cell-index = <0>;
> + compatible = "fsl-i2c";
> + reg = <0x3100 0x100>;
> + interrupts = <15 0x8>;
> + interrupt-parent = <&ipic>;
> + dfsrr;
> + pwm@28 {
> + compatible = "maxim,ds1050";
> + reg = <0x28>;
> + };
> + sensor0@48 {
> + compatible = "maxim,max6625";
> + reg = <0x48>;
> + };
> + sensor1@49 {
> + compatible = "maxim,max6625";
> + reg = <0x49>;
> + };
> + sensor2@4b {
> + compatible = "maxim,max6625";
> + reg = <0x4b>;
> + };
> + };
Why "i2c0@3000" and "i2c1@3100" rather than "i2c@3000" and "i2c@3100"?
Likewise for the sensor nodes.
Drop cell-index; it's not part of the fsl i2c binding (plus, they
probably shouldn't both be zero...).
> + enet0: ethernet@24000 {
> + #address-cells = <1>;
> + #size-cells = <1>;
> + ranges = <0x0 0x24000 0x1000>;
> +
> + cell-index = <0>;
> + device_type = "network";
> + model = "eTSEC";
> + compatible = "gianfar";
> + reg = <0x24000 0x1000>;
> + local-mac-address = [ 00 00 00 00 00 00 ];
> + interrupts = <32 0x8 33 0x8 34 0x8>;
> + interrupt-parent = <&ipic>;
> + phy-handle = < &phy1 >;
> + fsl,magic-packet;
8308 does not have magic packet.
> + gpio@c00 {
> + #gpio-cells = <2>;
> + device_type = "gpio";
> + compatible = "fsl,mpc8308-gpio", "fsl,mpc8349-gpio";
> + reg = <0xc00 0x18>;
> + interrupts = <74 0x8>;
> + interrupt-parent = <&ipic>;
> + gpio-controller;
> + };
Drop device_type.
> + pci0: pcie@e0009000 {
> + #address-cells = <3>;
> + #size-cells = <2>;
> + #interrupt-cells = <1>;
> + device_type = "pci";
> + compatible = "fsl,mpc8308-pcie", "fsl,mpc8314-pcie";
> + reg = <0xe0009000 0x00001000
> + 0xb0000000 0x01000000>;
> + ranges = <0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
> + 0x01000000 0 0x00000000 0xb1000000 0 0x00800000>;
> + bus-range = <0 0>;
> + interrupt-map-mask = <0xf800 0 0 7>;
> + interrupt-map = <0 0 0 1 &ipic 1 8
> + 0 0 0 2 &ipic 1 8
> + 0 0 0 3 &ipic 1 8
> + 0 0 0 4 &ipic 1 8>;
Should interrupt-map-mask be <0 0 0 7>? Or possibly <0 0 0 0> with
just one map entry?
-Scott
^ permalink raw reply
* Re: Small issue at init with spi_mpc8xxx.c with CPM1
From: Scott Wood @ 2010-09-07 20:00 UTC (permalink / raw)
To: LEROY Christophe; +Cc: Kumar Gala, LinuxPPC-dev
In-Reply-To: <4C86031D.5080804@c-s.fr>
On Tue, 7 Sep 2010 11:17:17 +0200
LEROY Christophe <christophe.leroy@c-s.fr> wrote:
>
> Dear Kumar,
>
> I have a small issue in the init of spi_mpc8xxx.c with MPC866 (CPM1)
>
> Unlike cpm_uart that maps the parameter ram directly using
> of_iomap(np,1), spi_mpc8xxx.c uses cpm_muram_alloc_fixed().
>
> This has two impacts in the .dts file:
> * The driver must be declared with pram at 1d80 instead of 3d80 whereas
> it is not a child of muram@2000 but a child of cpm@9c0
> * muram@2000/data@0 must be declared with reg = <0x0 0x2000> whereas
> is should be reg=<0x0 0x1c00> to avoid cpm_muram_alloc() to allocate
> space from parameters ram.
>
> Maybe I misunderstood something ?
Don't make the device tree lie, fix the driver instead.
The allocator should not be given any chunks of muram that are
dedicated to a fixed purpose -- it might hand it out to something else
before you reserve it. I don't think that cpm_muram_alloc_fixed() has
any legitimate use at all.
-Scott
^ permalink raw reply
* linux-2.6.36-rc3 bug report
From: d binderman @ 2010-09-07 19:00 UTC (permalink / raw)
To: benh, paulus; +Cc: linuxppc-dev
Hello there=2C
I just tried out cppcheck-1.44 on the linux-2.6.36-rc3 source code.
It said
Checking arch/powerpc/kernel/ppc970-pmu.c...
[arch/powerpc/kernel/ppc970-pmu.c:171]: (style) Redundant assignment of "ma=
sk" in switch
The source code is
=A0=A0=A0=A0=A0=A0=A0 case PM_VPU:
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 mask =3D 0x4c=3B=A0=A0=A0=A0=
=A0=A0=A0=A0=A0=A0=A0 /* byte 0 bits 2=2C3=2C6 */
=A0=A0=A0=A0=A0=A0=A0 case PM_LSU0:
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 /* byte 2 bits 0=2C2=2C3=2C4=
=2C6=3B all of byte 1 */
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 mask =3D 0x085dff00=3B
=A0=A0=A0=A0=A0=A0=A0 case PM_LSU1L:
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 mask =3D 0x50 << 24=3B=A0=A0=
=A0=A0=A0 /* byte 3 bits 4=2C6 */
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 break=3B
It looks to me like a missing break on the first and second cases.
Suggest code rework.
Regards
David Binderman
=
^ permalink raw reply
* [RFC] arch/powerpc: Remove duplicate/redundant Altivec entries
From: Matthew McClintock @ 2010-09-07 18:56 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Matthew McClintock
In lieu of having multiple similiar lines, we can just have one
generic cpu-as line for CONFIG_ALTIVEC
---
Was hoping to get comments about this change and if anyone sees any potential
problems?
arch/powerpc/Makefile | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index e07d499..4e88b42 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -131,8 +131,7 @@ KBUILD_CFLAGS += -mno-sched-epilog
endif
cpu-as-$(CONFIG_4xx) += -Wa,-m405
-cpu-as-$(CONFIG_6xx) += -Wa,-maltivec
-cpu-as-$(CONFIG_POWER4) += -Wa,-maltivec
+cpu-as-$(CONFIG_ALTIVEC) += -Wa,-maltivec
cpu-as-$(CONFIG_E500) += -Wa,-me500
cpu-as-$(CONFIG_E200) += -Wa,-me200
--
1.6.6.1
^ permalink raw reply related
* kexec on ppc64
From: Matthew McClintock @ 2010-09-07 18:34 UTC (permalink / raw)
To: kexec; +Cc: linuxppc-dev
All,
I'm trying to determine how kexec'ing works on 64 bit powerpc. When =
allocating a region for the kexec'ed kernel is it ever the same as the =
currently running kernel or do you always boot the kexec'ed kernel from =
a different memory region? I understand that a crash kernel will be in a =
different region, however I was hoping to confirm the behavior for a =
normal "kexec -e".
Thanks,
Matthew=
^ permalink raw reply
* [PATCH] mpc8308_p1m: support for MPC8308 P1M board
From: Ilya Yanok @ 2010-09-07 10:09 UTC (permalink / raw)
To: linuxppc-dev, wd, dzu, vlad; +Cc: Ilya Yanok
This patch adds support for MPC8308 P1M board.
Supported devices:
DUART
Dual Ethernet
NOR flash
Both I2C controllers
USB in peripheral mode
PCI Express
Signed-off-by: Ilya Yanok <yanok@emcraft.com>
---
arch/powerpc/boot/dts/mpc8308_p1m.dts | 340 +++++++++++++++++++++++++++++
arch/powerpc/platforms/83xx/Kconfig | 4 +-
arch/powerpc/platforms/83xx/mpc830x_rdb.c | 3 +-
3 files changed, 344 insertions(+), 3 deletions(-)
create mode 100644 arch/powerpc/boot/dts/mpc8308_p1m.dts
diff --git a/arch/powerpc/boot/dts/mpc8308_p1m.dts b/arch/powerpc/boot/dts/mpc8308_p1m.dts
new file mode 100644
index 0000000..159a0d0
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8308_p1m.dts
@@ -0,0 +1,340 @@
+/*
+ * mpc8308_p1m Device Tree Source
+ *
+ * Copyright 2010 Ilya Yanok, Emcraft Systems, yanok@emcraft.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.
+ */
+
+/dts-v1/;
+
+/ {
+ compatible = "mpc8308_p1m";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ aliases {
+ ethernet0 = &enet0;
+ ethernet1 = &enet1;
+ serial0 = &serial0;
+ serial1 = &serial1;
+ pci0 = &pci0;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PowerPC,8308@0 {
+ device_type = "cpu";
+ reg = <0x0>;
+ d-cache-line-size = <32>;
+ i-cache-line-size = <32>;
+ d-cache-size = <16384>;
+ i-cache-size = <16384>;
+ timebase-frequency = <0>; // from bootloader
+ bus-frequency = <0>; // from bootloader
+ clock-frequency = <0>; // from bootloader
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x08000000>; // 128MB at 0
+ };
+
+ localbus@e0005000 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8315-elbc", "fsl,elbc", "simple-bus";
+ reg = <0xe0005000 0x1000>;
+ interrupts = <77 0x8>;
+ interrupt-parent = <&ipic>;
+
+ ranges = <0x0 0x0 0xfc000000 0x04000000
+ 0x1 0x0 0xfbff0000 0x00008000
+ 0x2 0x0 0xfbff8000 0x00008000>;
+
+ flash@0,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "cfi-flash";
+ reg = <0x0 0x0 0x4000000>;
+ bank-width = <2>;
+ device-width = <1>;
+
+ u-boot@0 {
+ reg = <0x0 0x60000>;
+ read-only;
+ };
+ env@60000 {
+ reg = <0x60000 0x20000>;
+ };
+ env1@80000 {
+ reg = <0x80000 0x20000>;
+ };
+ kernel@a0000 {
+ reg = <0xa0000 0x200000>;
+ };
+ dtb@2a0000 {
+ reg = <0x2a0000 0x20000>;
+ };
+ ramdisk@2c0000 {
+ reg = <0x2c0000 0x640000>;
+ };
+ user@700000 {
+ reg = <0x700000 0x3900000>;
+ };
+ };
+
+ can@1,0 {
+ compatible = "nxp,sja1000";
+ reg = <0x1 0x0 0x80>;
+ interrupts = <18 0x8>;
+ interrups-parent = <&ipic>;
+ };
+
+ cpld@2,0 {
+ compatible = "cpld";
+ reg = <0x2 0x0 0x8>;
+ interrupts = <48 0x8>;
+ interrups-parent = <&ipic>;
+ };
+ };
+
+ immr@e0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+ compatible = "fsl,mpc8308-immr", "simple-bus";
+ ranges = <0 0xe0000000 0x00100000>;
+ reg = <0xe0000000 0x00000200>;
+ bus-frequency = <0>;
+
+ i2c0@3000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+ reg = <0x3000 0x100>;
+ interrupts = <14 0x8>;
+ interrupt-parent = <&ipic>;
+ dfsrr;
+ fram@50 {
+ compatible = "ramtron,24c64";
+ reg = <0x50>;
+ };
+ };
+
+ i2c1@3100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+ reg = <0x3100 0x100>;
+ interrupts = <15 0x8>;
+ interrupt-parent = <&ipic>;
+ dfsrr;
+ pwm@28 {
+ compatible = "maxim,ds1050";
+ reg = <0x28>;
+ };
+ sensor0@48 {
+ compatible = "maxim,max6625";
+ reg = <0x48>;
+ };
+ sensor1@49 {
+ compatible = "maxim,max6625";
+ reg = <0x49>;
+ };
+ sensor2@4b {
+ compatible = "maxim,max6625";
+ reg = <0x4b>;
+ };
+ };
+
+ usb@23000 {
+ compatible = "fsl-usb2-dr";
+ reg = <0x23000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupt-parent = <&ipic>;
+ interrupts = <38 0x8>;
+ dr_mode = "peripheral";
+ phy_type = "ulpi";
+ };
+
+ enet0: ethernet@24000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x24000 0x1000>;
+
+ cell-index = <0>;
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "gianfar";
+ reg = <0x24000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <32 0x8 33 0x8 34 0x8>;
+ interrupt-parent = <&ipic>;
+ phy-handle = < &phy1 >;
+ fsl,magic-packet;
+
+ mdio@520 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,gianfar-mdio";
+ reg = <0x520 0x20>;
+ phy1: ethernet-phy@1 {
+ interrupt-parent = <&ipic>;
+ interrupts = <17 0x8>;
+ reg = <0x1>;
+ device_type = "ethernet-phy";
+ };
+ phy2: ethernet-phy@2 {
+ interrupt-parent = <&ipic>;
+ interrupts = <19 0x8>;
+ reg = <0x2>;
+ device_type = "ethernet-phy";
+ };
+ tbi0: tbi-phy@11 {
+ reg = <0x11>;
+ device_type = "tbi-phy";
+ };
+ };
+ };
+
+ enet1: ethernet@25000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ cell-index = <1>;
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "gianfar";
+ reg = <0x25000 0x1000>;
+ ranges = <0x0 0x25000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <35 0x8 36 0x8 37 0x8>;
+ interrupt-parent = <&ipic>;
+ phy-handle = < &phy2 >;
+ fsl,magic-packet;
+
+ mdio@520 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,gianfar-tbi";
+ reg = <0x520 0x20>;
+ tbi1: tbi-phy@11 {
+ reg = <0x11>;
+ device_type = "tbi-phy";
+ };
+ };
+ };
+
+ serial0: serial@4500 {
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x4500 0x100>;
+ clock-frequency = <133333333>;
+ interrupts = <9 0x8>;
+ interrupt-parent = <&ipic>;
+ };
+
+ serial1: serial@4600 {
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x4600 0x100>;
+ clock-frequency = <133333333>;
+ interrupts = <10 0x8>;
+ interrupt-parent = <&ipic>;
+ };
+
+ gpio@c00 {
+ #gpio-cells = <2>;
+ device_type = "gpio";
+ compatible = "fsl,mpc8308-gpio", "fsl,mpc8349-gpio";
+ reg = <0xc00 0x18>;
+ interrupts = <74 0x8>;
+ interrupt-parent = <&ipic>;
+ gpio-controller;
+ };
+
+ timer@500 {
+ compatible = "fsl,mpc8308-gtm", "fsl,gtm";
+ reg = <0x500 0x100>;
+ interrupts = <90 8 78 8 84 8 72 8>;
+ interrupt-parent = <&ipic>;
+ clock-frequency = <133333333>;
+ };
+
+ /* IPIC
+ * interrupts cell = <intr #, sense>
+ * sense values match linux IORESOURCE_IRQ_* defines:
+ * sense == 8: Level, low assertion
+ * sense == 2: Edge, high-to-low change
+ */
+ ipic: interrupt-controller@700 {
+ compatible = "fsl,ipic";
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ reg = <0x700 0x100>;
+ device_type = "ipic";
+ };
+
+ ipic-msi@7c0 {
+ compatible = "fsl,ipic-msi";
+ reg = <0x7c0 0x40>;
+ msi-available-ranges = <0x0 0x100>;
+ interrupts = < 0x43 0x8
+ 0x4 0x8
+ 0x51 0x8
+ 0x52 0x8
+ 0x56 0x8
+ 0x57 0x8
+ 0x58 0x8
+ 0x59 0x8 >;
+ interrupt-parent = < &ipic >;
+ };
+
+ };
+
+ pci0: pcie@e0009000 {
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ device_type = "pci";
+ compatible = "fsl,mpc8308-pcie", "fsl,mpc8314-pcie";
+ reg = <0xe0009000 0x00001000
+ 0xb0000000 0x01000000>;
+ ranges = <0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
+ 0x01000000 0 0x00000000 0xb1000000 0 0x00800000>;
+ bus-range = <0 0>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <0 0 0 1 &ipic 1 8
+ 0 0 0 2 &ipic 1 8
+ 0 0 0 3 &ipic 1 8
+ 0 0 0 4 &ipic 1 8>;
+ interrupts = <0x1 0x8>;
+ interrupt-parent = <&ipic>;
+ clock-frequency = <0>;
+
+ pcie@0 {
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ reg = <0 0 0 0 0>;
+ ranges = <0x02000000 0 0xa0000000
+ 0x02000000 0 0xa0000000
+ 0 0x10000000
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00800000>;
+ };
+ };
+};
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 021763a..73f4135 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -10,12 +10,12 @@ menuconfig PPC_83xx
if PPC_83xx
config MPC830x_RDB
- bool "Freescale MPC830x RDB"
+ bool "Freescale MPC830x RDB and derivatives"
select DEFAULT_UIMAGE
select PPC_MPC831x
select FSL_GTM
help
- This option enables support for the MPC8308 RDB board.
+ This option enables support for the MPC8308 RDB and MPC8308 P1M boards.
config MPC831x_RDB
bool "Freescale MPC831x RDB"
diff --git a/arch/powerpc/platforms/83xx/mpc830x_rdb.c b/arch/powerpc/platforms/83xx/mpc830x_rdb.c
index ac102ee..aa7ef69 100644
--- a/arch/powerpc/platforms/83xx/mpc830x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc830x_rdb.c
@@ -65,7 +65,8 @@ static int __init mpc830x_rdb_probe(void)
unsigned long root = of_get_flat_dt_root();
return of_flat_dt_is_compatible(root, "MPC8308RDB") ||
- of_flat_dt_is_compatible(root, "fsl,mpc8308rdb");
+ of_flat_dt_is_compatible(root, "fsl,mpc8308rdb") ||
+ of_flat_dt_is_compatible(root, "mpc8308_p1m");
}
static struct of_device_id __initdata of_bus_ids[] = {
--
1.6.2.5
^ permalink raw reply related
* Re: pci_request_regions() failure
From: tiejun.chen @ 2010-09-07 9:24 UTC (permalink / raw)
To: Ravi Gupta; +Cc: linuxppc-dev
In-Reply-To: <AANLkTi=bDOtCxW9VuXrSyAiCLoFCvWoskORpc_1ebDe7@mail.gmail.com>
Ravi Gupta wrote:
> Hi Tiejun,
>
> Thanks for the reply. I am sending you the updated dmesg O/P(after enabling
> CONFIG_PCI_DEBUG) as attachment as well as at the end of the mail.
>
> As far as driver is concern, I am trying the pci_skel driver available as
> example with LDD book with slight modifications.
Current LDD 3rd may be old for 2.6.35 on some sections :)
>
> Driver Code:
> ================================================================
> #include <linux/kernel.h>
> #include <linux/module.h>
> #include <linux/pci.h>
>
> /* PCI IDs */
> static struct pci_device_id ids[] = {
> { PCI_DEVICE(0x1204, 0xe250) },
> { 0, }
> };
> MODULE_DEVICE_TABLE(pci, ids);
>
> static unsigned char skel_get_revision(struct pci_dev *dev)
> {
> u8 revision;
>
> pci_read_config_byte(dev, PCI_REVISION_ID, &revision);
> return revision;
> }
>
> static u16 skel_get_vendor_id(struct pci_dev *dev)
> {
> u16 vendor_id;
>
> pci_read_config_word(dev, PCI_VENDOR_ID, &vendor_id);
> return vendor_id;
> }
>
> static u16 skel_get_device_id(struct pci_dev *dev)
> {
> u16 device_id;
>
> pci_read_config_word(dev, PCI_DEVICE_ID, &device_id);
> return device_id;
> }
>
> static int probe(struct pci_dev *dev, const struct pci_device_id *id)
> {
> /* Do probing type stuff here.
> * Like calling request_region();
> */
> int err, i;
> printk(KERN_ALERT "PCI driver: Probe function\n");
>
> /*
> * Enable the bus-master bit values.
> * Some PCI BIOSes fail to set the master-enable bit.
> * Some demos support being an initiator, so need bus master ability.
> */
> err = pci_request_regions(dev, "pci_skell");
> if (err) {
> printk(KERN_ERR "request region failed :%d\n", err);
> return err;
> }
>
> pci_set_master(dev);
>
> if ((err = pci_enable_device(dev)) != 0) {
> printk(KERN_ERR "Unable to Enable PCI device:%d\n", err);
> return err;
> }
>
> printk(KERN_ALERT "PCI driver Vendor ID = %x\n", skel_get_vendor_id(dev));
> printk(KERN_ALERT "PCI driver Device ID = %x\n", skel_get_device_id(dev));
> printk(KERN_ALERT "PCI driver Revision = %d\n", skel_get_revision(dev));
> return 0;
> }
>
> static void remove(struct pci_dev *dev)
> {
> /* clean up any allocated resources and stuff here.
> * like call release_region();
> */
> }
>
> static struct pci_driver pci_driver = {
> .name = "pci_skel",
> .id_table = ids,
> .probe = probe,
> .remove = remove,
> };
>
> static int __init pci_skel_init(void)
> {
> printk(KERN_ALERT "PCI driver: Init function\n");
> return pci_register_driver(&pci_driver);
> }
>
> static void __exit pci_skel_exit(void)
> {
> printk(KERN_ALERT "PCI driver: Exit function\n");
> pci_unregister_driver(&pci_driver);
> }
>
> MODULE_LICENSE("GPL");
>
> module_init(pci_skel_init);
> module_exit(pci_skel_exit);
> ================================================================
>
> The above code fails at the pci_request_regions(dev, "pci_skell"); call,
> with -EBUSY(-16) i.e resource busy error. If I don't request for resources
> and directly enable the pci device by calling pci_device_enable(), it gives
> the error message
>
> PCI driver: Init function
> PCI driver: Probe function
> pci_skel 0001:02:00.0: device not available (can't reserve [mem
> 0x00000000-0x0003ffff])
> Unable to Enable PCI device:-22
> pci_skel: probe of 0001:02:00.0 failed with error -22
Your PCI device should be one virtual device so I think the above should be as
we understood. You know 0x00000000 ~ 0x00003ffff should not be allowed to
reserved.
>
>
>
>> Especially I want to know how/where you get
>> these two range, a8000000-a803ffff and a8040000-a807ffff. You wired them
> firstly
>> on the driver or allocated by the kernel?
>
> Actually as I said before, I tried my device on i386 machine and there I got
> two ranges fe900000-fe93ffff and fe940000-fe97ffff, so from there I am
> guessing that on PowerPC also, it should allocate two ranges
> a8000000-a803ffff and a8040000-a807ffff resp.
I think you should do the following sequence in the probe function of your PCI
driver.
1. pci_enable_device(pdev);
2. pci_request_regions(pdev, DRV_NAME);
3. pci_set_master(pdev);
......
>
>
>
> lspci output
> ================================================================
> 0000:00:00.0 Power PC: Freescale Semiconductor Inc Unknown device 00c6 (rev
> 21)
> 0001:01:00.0 PCI bridge: Freescale Semiconductor Inc Unknown device 00c6
> (rev 21)
> 0001:02:00.0 Non-VGA unclassified device: Lattice Semiconductor Corporation
> Unknown device e250 ----------> My device
> ================================================================
>
> Dmesg with CONFIG_PCI_DEBUG enable.
> ================================================================
> Using MPC837x RDB/WLAN machine description
> Initializing cgroup subsys cpuset
> Initializing cgroup subsys cpu
> Linux version 2.6.35 (okapi@okapi) (gcc version 4.2.3 (Sourcery G++ Lite
> 4.2-171)) #13 Tue Sep 7 11:37:47 IST 2010
> Found initrd at 0xcf46d000:0xcf7b15b7
> Found legacy serial port 0 for /immr@e0000000/serial@4500
> mem=e0004500, taddr=e0004500, irq=0, clk=399999996, speed=0
> Found legacy serial port 1 for /immr@e0000000/serial@4600
> mem=e0004600, taddr=e0004600, irq=0, clk=399999996, speed=0
> bootconsole [udbg0] enabled
> Found FSL PCI host bridge at 0x00000000e0008500. Firmware bus number: 0->0
> PCI host bridge /pci@e0008500 (primary) ranges:
> MEM 0x0000000090000000..0x000000009fffffff -> 0x0000000090000000
> MEM 0x0000000080000000..0x000000008fffffff -> 0x0000000080000000 Prefetch
> IO 0x00000000e0300000..0x00000000e03fffff -> 0x0000000000000000
> No pci config register base in dev tree, using default
> Found FSL PCI host bridge at 0x00000000e0009000. Firmware bus number: 0->255
> PCI host bridge /pcie@e0009000 ranges:
> MEM 0x00000000a8000000..0x00000000b7ffffff -> 0x00000000a8000000
> IO 0x00000000b8000000..0x00000000b87fffff -> 0x0000000000000000
> No pci config register base in dev tree, using default
> Found FSL PCI host bridge at 0x00000000e000a000. Firmware bus number: 0->255
> PCI host bridge /pcie@e000a000 ranges:
> MEM 0x00000000c8000000..0x00000000d7ffffff -> 0x00000000c8000000
> IO 0x00000000d8000000..0x00000000d87fffff -> 0x0000000000000000
> Top of RAM: 0x10000000, Total RAM: 0x10000000
> Memory hole size: 0MB
> Zone PFN ranges:
> DMA 0x00000000 -> 0x00010000
> Normal empty
> HighMem empty
> Movable zone start PFN for each node
> early_node_map[1] active PFN ranges
> 0: 0x00000000 -> 0x00010000
> On node 0 totalpages: 65536
> free_area_init_node: node 0, pgdat c04285e8, node_mem_map c0482000
> DMA zone: 512 pages used for memmap
> DMA zone: 0 pages reserved
> DMA zone: 65024 pages, LIFO batch:15
> Built 1 zonelists in Zone order, mobility grouping on. Total pages: 65024
> Kernel command line: root=/dev/ram ramdisk_size=120000 rw ip=10.20.50.230:10
> .20.50.70:10.20.50.50:255.255.0.0:PowerQUICC:eth0:off console=ttyS0,115200
> mtdparts=nand:4m(kernel),-(jffs2)
> PID hash table entries: 1024 (order: 0, 4096 bytes)
> Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
> Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
> High memory: 0k
> Memory: 251884k/262144k available (4072k kernel code, 10260k reserved, 244k
> data, 267k bss, 192k init)
> Kernel virtual memory layout:
> * 0xfffcf000..0xfffff000 : fixmap
> * 0xff800000..0xffc00000 : highmem PTEs
> * 0xfe6f7000..0xff800000 : early ioremap
> * 0xd1000000..0xfe6f7000 : vmalloc & ioremap
> Hierarchical RCU implementation.
> RCU-based detection of stalled CPUs is disabled.
> Verbose stalled-CPUs detection is disabled.
> NR_IRQS:512
> IPIC (128 IRQ sources) at d1000700
> time_init: decrementer frequency = 99.999999 MHz
> time_init: processor frequency = 799.999992 MHz
> clocksource: timebase mult[2800000] shift[22] registered
> clockevent: decrementer mult[19999995] shift[32] cpu[0]
> Console: colour dummy device 80x25
> pid_max: default: 32768 minimum: 301
> Security Framework initialized
> SELinux: Disabled at boot.
> Mount-cache hash table entries: 512
> Initializing cgroup subsys ns
> Initializing cgroup subsys cpuacct
> Initializing cgroup subsys devices
> NET: Registered protocol family 16
> irq: irq 38 on host /immr@e0000000/interrupt-controller@700 mapped to
> virtual irq 38
> __irq_set_trigger: setting type, irq = 38, flags = 8
> ipic_set_irq_type function, with virq = 38, flow = 8
> irq: irq 74 on host /immr@e0000000/interrupt-controller@700 mapped to
> virtual irq 74
> __irq_set_trigger: setting type, irq = 74, flags = 8
> ipic_set_irq_type function, with virq = 74, flow = 8
> irq: irq 75 on host /immr@e0000000/interrupt-controller@700 mapped to
> virtual irq 75
> __irq_set_trigger: setting type, irq = 75, flags = 8
> ipic_set_irq_type function, with virq = 75, flow = 8
> PCI: Probing PCI hardware
> pci_bus 0000:00: scanning bus
> pci 0000:00:00.0: found [1957:00c6] class 000b20 header type 00
> pci 0000:00:00.0: reg 10: [mem 0x00000000-0x000fffff]
> pci 0000:00:00.0: reg 18: [mem 0x00000000-0x0fffffff 64bit pref]
> pci 0000:00:00.0: calling fixup_hide_host_resource_fsl+0x0/0x58
> pci 0000:00:00.0: calling pcibios_fixup_resources+0x0/0x238
> pci 0000:00:00.0: calling quirk_fsl_pcie_header+0x0/0x48
> pci 0000:00:00.0: calling quirk_resource_alignment+0x0/0x1c0
> pci 0000:00:00.0: supports D1 D2
> pci 0000:00:00.0: PME# supported from D0 D1 D2 D3hot
> pci 0000:00:00.0: PME# disabled
> pci_bus 0000:00: fixups for bus
> pci_bus 0000:00: bus scan returning with max=00
> pci_bus 0001:01: scanning bus
> pci 0001:01:00.0: found [1957:00c6] class 000b20 header type 01
> pci 0001:01:00.0: ignoring class b20 (doesn't match header type 01)
> pci 0001:01:00.0: calling fixup_hide_host_resource_fsl+0x0/0x58
> pci 0001:01:00.0: calling pcibios_fixup_resources+0x0/0x238
> pci 0001:01:00.0: calling quirk_fsl_pcie_header+0x0/0x48
> pci 0001:01:00.0: calling quirk_resource_alignment+0x0/0x1c0
> pci 0001:01:00.0: supports D1 D2
> pci 0001:01:00.0: PME# supported from D0 D1 D2 D3hot
> pci 0001:01:00.0: PME# disabled
> pci_bus 0001:01: fixups for bus
> pci 0001:01:00.0: scanning [bus 01-ff] behind bridge, pass 0
> pci 0001:01:00.0: bus configuration invalid, reconfiguring
> pci 0001:01:00.0: scanning [bus 00-00] behind bridge, pass 1
> pci_bus 0001:02: scanning bus
> pci 0001:02:00.0: found [1204:e250] class 000000 header type 00
> pci 0001:02:00.0: reg 10: [mem 0xfffc0000-0xffffffff]
> pci 0001:02:00.0: reg 14: [mem 0xfffc0000-0xffffffff]
These infos make me confused. 0xfxxxxxxx should not be original BARs value and
also cannot be allocated for resources successfully by the kernel.
Often the kernel get them to allocate as PCI bus range. For example,
Firstly checking.....
-------
pci 0001:02:00.0: reg 10: [mem 0x00000000-0x00003fff 64bit]
pci 0001:02:00.0: reg 18: [io 0x0000-0x00ff]
pci 0001:02:00.0: reg 30: [mem 0x00000000-0x0001ffff pref]
Then allocating as the following:
-------
pci 0001:02:00.0: BAR 6: assigned [mem 0xa0000000-0xa001ffff pref]
pci 0001:02:00.0: BAR 0: assigned [mem 0xa0020000-0xa0023fff 64bit]
pci 0001:02:00.0: BAR 0: set to [mem 0xa0020000-0xa0023fff 64bit] (PCI address
[0xa0020000-0xa0023fff]
So I think your device BARs should be pre-allocated incorrectly by the
bootloader since your device is so special. Maybe this is just why that's
different from you saw on x86. As a result we cannot re-allocated into PCI bus
range as the kernel expect.
Looks we need some pci_fixup to modify them. Firstly I think you'd better 'zero'
all BARs of your PCI device on the function, pci_scan_device, on the file,
drivers/pci/probe.c. On there you can dedicate that once your device is probed.
Please check the each BAR's value again after the above fix.
Best Regards
Tiejun
> pci 0001:02:00.0: calling pcibios_fixup_resources+0x0/0x238
> pci 0001:02:00.0: calling quirk_resource_alignment+0x0/0x1c0
> pci_bus 0001:02: fixups for bus
> pci 0001:01:00.0: PCI bridge to [bus 02-ff]
> pci 0001:01:00.0: bridge window [io 0x0000-0x0000] (disabled)
> pci 0001:01:00.0: bridge window [mem 0x00000000-0x000fffff] (disabled)
> pci 0001:01:00.0: bridge window [mem 0x00000000-0x000fffff pref]
> (disabled)
> irq: irq 1 on host /immr@e0000000/interrupt-controller@700 mapped to virtual
> irq 16
> __irq_set_trigger: setting type, irq = 16, flags = 8
> ipic_set_irq_type function, with virq = 16, flow = 8
> pci_bus 0001:02: bus scan returning with max=02
> pci_bus 0001:01: bus scan returning with max=02
> pci_bus 0002:03: scanning bus
> pci_bus 0002:03: fixups for bus
> pci_bus 0002:03: bus scan returning with max=03
> PCI->OF bus map:
> 0 -> 0
> 1 -> 0
> 3 -> 0
> PCI: Cannot allocate resource region 0 of device 0001:02:00.0, will remap
> PCI: Cannot allocate resource region 1 of device 0001:02:00.0, will remap
> pci 0001:01:00.0: BAR 8: assigned [mem 0xa8000000-0xa80fffff]
> pci 0001:01:00.0: PCI bridge to [bus 02-02]
> pci 0001:01:00.0: bridge window [io disabled]
> pci 0001:01:00.0: bridge window [mem 0xa8000000-0xa80fffff]
> pci 0001:01:00.0: bridge window [mem pref disabled]
> pci_bus 0000:00: resource 0 [io 0x0000-0xfffff]
> pci_bus 0000:00: resource 1 [mem 0x90000000-0x9fffffff]
> pci_bus 0000:00: resource 2 [mem 0x80000000-0x8fffffff pref]
> pci_bus 0001:01: resource 0 [io 0xff7fe000-0xffffdfff]
> pci_bus 0001:01: resource 1 [mem 0xa8000000-0xb7ffffff]
> pci_bus 0001:02: resource 1 [mem 0xa8000000-0xa80fffff]
> pci_bus 0002:03: resource 0 [io 0xfeffc000-0xff7fbfff]
> pci_bus 0002:03: resource 1 [mem 0xc8000000-0xd7ffffff]
> Registering qe_ic with sysfs...
> Registering ipic with sysfs...
> bio: create slab <bio-0> at 0
> vgaarb: loaded
> SCSI subsystem initialized
> Switching to clocksource timebase
> NET: Registered protocol family 2
> IP route cache hash table entries: 2048 (order: 1, 8192 bytes)
> TCP established hash table entries: 8192 (order: 4, 65536 bytes)
> TCP bind hash table entries: 8192 (order: 3, 32768 bytes)
> TCP: Hash tables configured (established 8192 bind 8192)
> TCP reno registered
> UDP hash table entries: 256 (order: 0, 4096 bytes)
> UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
> NET: Registered protocol family 1
> pci 0000:00:00.0: calling quirk_cardbus_legacy+0x0/0x44
> pci 0000:00:00.0: calling quirk_usb_early_handoff+0x0/0x740
> pci 0001:01:00.0: calling quirk_cardbus_legacy+0x0/0x44
> pci 0001:01:00.0: calling quirk_usb_early_handoff+0x0/0x740
> pci 0001:02:00.0: calling quirk_cardbus_legacy+0x0/0x44
> pci 0001:02:00.0: calling quirk_usb_early_handoff+0x0/0x740
> PCI: CLS 32 bytes, default 32
> Trying to unpack rootfs image as initramfs...
> rootfs image is not initramfs (no cpio magic); looks like an initrd
> Freeing initrd memory: 3345k freed
> irq: irq 9 on host /immr@e0000000/interrupt-controller@700 mapped to virtual
> irq 17
> __irq_set_trigger: setting type, irq = 17, flags = 8
> ipic_set_irq_type function, with virq = 17, flow = 8
> irq: irq 10 on host /immr@e0000000/interrupt-controller@700 mapped to
> virtual irq 18
> __irq_set_trigger: setting type, irq = 18, flags = 8
> ipic_set_irq_type function, with virq = 18, flow = 8
> irq: irq 80 on host /immr@e0000000/interrupt-controller@700 mapped to
> virtual irq 80
> __irq_set_trigger: setting type, irq = 80, flags = 8
> ipic_set_irq_type function, with virq = 80, flow = 8
> audit: initializing netlink socket (disabled)
> type=2000 audit(0.212:1): initialized
> JFFS2 version 2.2. (NAND) � 2001-2006 Red Hat, Inc.
> SGI XFS with security attributes, large block/inode numbers, no debug
> enabled
> msgmni has been set to 498
> alg: No test for cipher_null (cipher_null-generic)
> alg: No test for ecb(cipher_null) (ecb-cipher_null)
> alg: No test for digest_null (digest_null-generic)
> alg: No test for compress_null (compress_null-generic)
> alg: No test for stdrng (krng)
> Block layer SCSI generic (bsg) driver version 0.4 loaded (major 253)
> io scheduler noop registered
> io scheduler deadline registered
> io scheduler cfq registered (default)
> Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
> serial8250.0: ttyS0 at MMIO 0xe0004500 (irq = 17) is a 16550A
> console [ttyS0] enabled, bootconsole disabled
> serial8250.0: ttyS1 at MMIO 0xe0004600 (irq = 18) is a 16550A
> brd: module loaded
> of_mpc8xxx_spi_probe function called.
> irq: irq 16 on host /immr@e0000000/interrupt-controller@700 mapped to
> virtual irq 19
> __irq_set_trigger: setting type, irq = 19, flags = 8
> ipic_set_irq_type function, with virq = 19, flow = 8
> mpc8xxx_spi_probe function called.
> mpc8xxx_spi e0007000.spi: at 0xd1078000 (irq = 19), CPU mode
> irq: irq 32 on host /immr@e0000000/interrupt-controller@700 mapped to
> virtual irq 32
> __irq_set_trigger: setting type, irq = 32, flags = 8
> ipic_set_irq_type function, with virq = 32, flow = 8
> irq: irq 33 on host /immr@e0000000/interrupt-controller@700 mapped to
> virtual irq 33
> __irq_set_trigger: setting type, irq = 33, flags = 8
> ipic_set_irq_type function, with virq = 33, flow = 8
> irq: irq 34 on host /immr@e0000000/interrupt-controller@700 mapped to
> virtual irq 34
> __irq_set_trigger: setting type, irq = 34, flags = 8
> ipic_set_irq_type function, with virq = 34, flow = 8
> eth0: Gianfar Ethernet Controller Version 1.2, 04:00:00:00:00:0a
> eth0: Running with NAPI enabled
> eth0: RX BD ring size for Q[0]: 256
> eth0: TX BD ring size for Q[0]: 256
> irq: irq 35 on host /immr@e0000000/interrupt-controller@700 mapped to
> virtual irq 35
> __irq_set_trigger: setting type, irq = 35, flags = 8
> ipic_set_irq_type function, with virq = 35, flow = 8
> irq: irq 36 on host /immr@e0000000/interrupt-controller@700 mapped to
> virtual irq 36
> __irq_set_trigger: setting type, irq = 36, flags = 8
> ipic_set_irq_type function, with virq = 36, flow = 8
> irq: irq 37 on host /immr@e0000000/interrupt-controller@700 mapped to
> virtual irq 37
> __irq_set_trigger: setting type, irq = 37, flags = 8
> ipic_set_irq_type function, with virq = 37, flow = 8
> eth1: Gianfar Ethernet Controller Version 1.2, 00:00:00:00:00:00
> eth1: Running with NAPI enabled
> eth1: RX BD ring size for Q[0]: 256
> eth1: TX BD ring size for Q[0]: 256
> ucc_geth: QE UCC Gigabit Ethernet Controller
> Freescale PowerQUICC MII Bus: probed
> irq: irq 17 on host /immr@e0000000/interrupt-controller@700 mapped to
> virtual irq 20
> __irq_set_trigger: setting type, irq = 20, flags = 8
> ipic_set_irq_type function, with virq = 20, flow = 8
> Freescale PowerQUICC MII Bus: probed
> mice: PS/2 mouse device common for all mice
> Skipping unavailable LED gpio -19 (pwr)
> Skipping unavailable LED gpio -19 (hdd)
> TCP cubic registered
> NET: Registered protocol family 17
> registered taskstats version 1
> drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
> RAMDISK: gzip image found at block 0
> VFS: Mounted root (ext2 filesystem) on device 1:0.
> Freeing unused kernel memory: 192k init
> PHY: mdio@e0024520:02 - Link is Up - 10/Half
> ================================================================
>
> Regards
> Ravi Gupta
>
^ permalink raw reply
* Small issue at init with spi_mpc8xxx.c with CPM1
From: LEROY Christophe @ 2010-09-07 9:17 UTC (permalink / raw)
To: Kumar Gala; +Cc: LinuxPPC-dev
Dear Kumar,
I have a small issue in the init of spi_mpc8xxx.c with MPC866 (CPM1)
Unlike cpm_uart that maps the parameter ram directly using
of_iomap(np,1), spi_mpc8xxx.c uses cpm_muram_alloc_fixed().
This has two impacts in the .dts file:
* The driver must be declared with pram at 1d80 instead of 3d80 whereas
it is not a child of muram@2000 but a child of cpm@9c0
* muram@2000/data@0 must be declared with reg = <0x0 0x2000> whereas
is should be reg=<0x0 0x1c00> to avoid cpm_muram_alloc() to allocate
space from parameters ram.
Maybe I misunderstood something ?
Regards
Christophe Leroy
^ permalink raw reply
* Re: pci_request_regions() failure
From: Ravi Gupta @ 2010-09-07 7:20 UTC (permalink / raw)
To: tiejun.chen; +Cc: linuxppc-dev
In-Reply-To: <4C85CCD6.3020504@windriver.com>
[-- Attachment #1.1: Type: text/plain, Size: 17006 bytes --]
Hi Tiejun,
Thanks for the reply. I am sending you the updated dmesg O/P(after enabling
CONFIG_PCI_DEBUG) as attachment as well as at the end of the mail.
As far as driver is concern, I am trying the pci_skel driver available as
example with LDD book with slight modifications.
Driver Code:
================================================================
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
/* PCI IDs */
static struct pci_device_id ids[] = {
{ PCI_DEVICE(0x1204, 0xe250) },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, ids);
static unsigned char skel_get_revision(struct pci_dev *dev)
{
u8 revision;
pci_read_config_byte(dev, PCI_REVISION_ID, &revision);
return revision;
}
static u16 skel_get_vendor_id(struct pci_dev *dev)
{
u16 vendor_id;
pci_read_config_word(dev, PCI_VENDOR_ID, &vendor_id);
return vendor_id;
}
static u16 skel_get_device_id(struct pci_dev *dev)
{
u16 device_id;
pci_read_config_word(dev, PCI_DEVICE_ID, &device_id);
return device_id;
}
static int probe(struct pci_dev *dev, const struct pci_device_id *id)
{
/* Do probing type stuff here.
* Like calling request_region();
*/
int err, i;
printk(KERN_ALERT "PCI driver: Probe function\n");
/*
* Enable the bus-master bit values.
* Some PCI BIOSes fail to set the master-enable bit.
* Some demos support being an initiator, so need bus master ability.
*/
err = pci_request_regions(dev, "pci_skell");
if (err) {
printk(KERN_ERR "request region failed :%d\n", err);
return err;
}
pci_set_master(dev);
if ((err = pci_enable_device(dev)) != 0) {
printk(KERN_ERR "Unable to Enable PCI device:%d\n", err);
return err;
}
printk(KERN_ALERT "PCI driver Vendor ID = %x\n", skel_get_vendor_id(dev));
printk(KERN_ALERT "PCI driver Device ID = %x\n", skel_get_device_id(dev));
printk(KERN_ALERT "PCI driver Revision = %d\n", skel_get_revision(dev));
return 0;
}
static void remove(struct pci_dev *dev)
{
/* clean up any allocated resources and stuff here.
* like call release_region();
*/
}
static struct pci_driver pci_driver = {
.name = "pci_skel",
.id_table = ids,
.probe = probe,
.remove = remove,
};
static int __init pci_skel_init(void)
{
printk(KERN_ALERT "PCI driver: Init function\n");
return pci_register_driver(&pci_driver);
}
static void __exit pci_skel_exit(void)
{
printk(KERN_ALERT "PCI driver: Exit function\n");
pci_unregister_driver(&pci_driver);
}
MODULE_LICENSE("GPL");
module_init(pci_skel_init);
module_exit(pci_skel_exit);
================================================================
The above code fails at the pci_request_regions(dev, "pci_skell"); call,
with -EBUSY(-16) i.e resource busy error. If I don't request for resources
and directly enable the pci device by calling pci_device_enable(), it gives
the error message
PCI driver: Init function
PCI driver: Probe function
pci_skel 0001:02:00.0: device not available (can't reserve [mem
0x00000000-0x0003ffff])
Unable to Enable PCI device:-22
pci_skel: probe of 0001:02:00.0 failed with error -22
> Especially I want to know how/where you get
> these two range, a8000000-a803ffff and a8040000-a807ffff. You wired them
firstly
> on the driver or allocated by the kernel?
Actually as I said before, I tried my device on i386 machine and there I got
two ranges fe900000-fe93ffff and fe940000-fe97ffff, so from there I am
guessing that on PowerPC also, it should allocate two ranges
a8000000-a803ffff and a8040000-a807ffff resp.
lspci output
================================================================
0000:00:00.0 Power PC: Freescale Semiconductor Inc Unknown device 00c6 (rev
21)
0001:01:00.0 PCI bridge: Freescale Semiconductor Inc Unknown device 00c6
(rev 21)
0001:02:00.0 Non-VGA unclassified device: Lattice Semiconductor Corporation
Unknown device e250 ----------> My device
================================================================
Dmesg with CONFIG_PCI_DEBUG enable.
================================================================
Using MPC837x RDB/WLAN machine description
Initializing cgroup subsys cpuset
Initializing cgroup subsys cpu
Linux version 2.6.35 (okapi@okapi) (gcc version 4.2.3 (Sourcery G++ Lite
4.2-171)) #13 Tue Sep 7 11:37:47 IST 2010
Found initrd at 0xcf46d000:0xcf7b15b7
Found legacy serial port 0 for /immr@e0000000/serial@4500
mem=e0004500, taddr=e0004500, irq=0, clk=399999996, speed=0
Found legacy serial port 1 for /immr@e0000000/serial@4600
mem=e0004600, taddr=e0004600, irq=0, clk=399999996, speed=0
bootconsole [udbg0] enabled
Found FSL PCI host bridge at 0x00000000e0008500. Firmware bus number: 0->0
PCI host bridge /pci@e0008500 (primary) ranges:
MEM 0x0000000090000000..0x000000009fffffff -> 0x0000000090000000
MEM 0x0000000080000000..0x000000008fffffff -> 0x0000000080000000 Prefetch
IO 0x00000000e0300000..0x00000000e03fffff -> 0x0000000000000000
No pci config register base in dev tree, using default
Found FSL PCI host bridge at 0x00000000e0009000. Firmware bus number: 0->255
PCI host bridge /pcie@e0009000 ranges:
MEM 0x00000000a8000000..0x00000000b7ffffff -> 0x00000000a8000000
IO 0x00000000b8000000..0x00000000b87fffff -> 0x0000000000000000
No pci config register base in dev tree, using default
Found FSL PCI host bridge at 0x00000000e000a000. Firmware bus number: 0->255
PCI host bridge /pcie@e000a000 ranges:
MEM 0x00000000c8000000..0x00000000d7ffffff -> 0x00000000c8000000
IO 0x00000000d8000000..0x00000000d87fffff -> 0x0000000000000000
Top of RAM: 0x10000000, Total RAM: 0x10000000
Memory hole size: 0MB
Zone PFN ranges:
DMA 0x00000000 -> 0x00010000
Normal empty
HighMem empty
Movable zone start PFN for each node
early_node_map[1] active PFN ranges
0: 0x00000000 -> 0x00010000
On node 0 totalpages: 65536
free_area_init_node: node 0, pgdat c04285e8, node_mem_map c0482000
DMA zone: 512 pages used for memmap
DMA zone: 0 pages reserved
DMA zone: 65024 pages, LIFO batch:15
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 65024
Kernel command line: root=/dev/ram ramdisk_size=120000 rw ip=10.20.50.230:10
.20.50.70:10.20.50.50:255.255.0.0:PowerQUICC:eth0:off console=ttyS0,115200
mtdparts=nand:4m(kernel),-(jffs2)
PID hash table entries: 1024 (order: 0, 4096 bytes)
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
High memory: 0k
Memory: 251884k/262144k available (4072k kernel code, 10260k reserved, 244k
data, 267k bss, 192k init)
Kernel virtual memory layout:
* 0xfffcf000..0xfffff000 : fixmap
* 0xff800000..0xffc00000 : highmem PTEs
* 0xfe6f7000..0xff800000 : early ioremap
* 0xd1000000..0xfe6f7000 : vmalloc & ioremap
Hierarchical RCU implementation.
RCU-based detection of stalled CPUs is disabled.
Verbose stalled-CPUs detection is disabled.
NR_IRQS:512
IPIC (128 IRQ sources) at d1000700
time_init: decrementer frequency = 99.999999 MHz
time_init: processor frequency = 799.999992 MHz
clocksource: timebase mult[2800000] shift[22] registered
clockevent: decrementer mult[19999995] shift[32] cpu[0]
Console: colour dummy device 80x25
pid_max: default: 32768 minimum: 301
Security Framework initialized
SELinux: Disabled at boot.
Mount-cache hash table entries: 512
Initializing cgroup subsys ns
Initializing cgroup subsys cpuacct
Initializing cgroup subsys devices
NET: Registered protocol family 16
irq: irq 38 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 38
__irq_set_trigger: setting type, irq = 38, flags = 8
ipic_set_irq_type function, with virq = 38, flow = 8
irq: irq 74 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 74
__irq_set_trigger: setting type, irq = 74, flags = 8
ipic_set_irq_type function, with virq = 74, flow = 8
irq: irq 75 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 75
__irq_set_trigger: setting type, irq = 75, flags = 8
ipic_set_irq_type function, with virq = 75, flow = 8
PCI: Probing PCI hardware
pci_bus 0000:00: scanning bus
pci 0000:00:00.0: found [1957:00c6] class 000b20 header type 00
pci 0000:00:00.0: reg 10: [mem 0x00000000-0x000fffff]
pci 0000:00:00.0: reg 18: [mem 0x00000000-0x0fffffff 64bit pref]
pci 0000:00:00.0: calling fixup_hide_host_resource_fsl+0x0/0x58
pci 0000:00:00.0: calling pcibios_fixup_resources+0x0/0x238
pci 0000:00:00.0: calling quirk_fsl_pcie_header+0x0/0x48
pci 0000:00:00.0: calling quirk_resource_alignment+0x0/0x1c0
pci 0000:00:00.0: supports D1 D2
pci 0000:00:00.0: PME# supported from D0 D1 D2 D3hot
pci 0000:00:00.0: PME# disabled
pci_bus 0000:00: fixups for bus
pci_bus 0000:00: bus scan returning with max=00
pci_bus 0001:01: scanning bus
pci 0001:01:00.0: found [1957:00c6] class 000b20 header type 01
pci 0001:01:00.0: ignoring class b20 (doesn't match header type 01)
pci 0001:01:00.0: calling fixup_hide_host_resource_fsl+0x0/0x58
pci 0001:01:00.0: calling pcibios_fixup_resources+0x0/0x238
pci 0001:01:00.0: calling quirk_fsl_pcie_header+0x0/0x48
pci 0001:01:00.0: calling quirk_resource_alignment+0x0/0x1c0
pci 0001:01:00.0: supports D1 D2
pci 0001:01:00.0: PME# supported from D0 D1 D2 D3hot
pci 0001:01:00.0: PME# disabled
pci_bus 0001:01: fixups for bus
pci 0001:01:00.0: scanning [bus 01-ff] behind bridge, pass 0
pci 0001:01:00.0: bus configuration invalid, reconfiguring
pci 0001:01:00.0: scanning [bus 00-00] behind bridge, pass 1
pci_bus 0001:02: scanning bus
pci 0001:02:00.0: found [1204:e250] class 000000 header type 00
pci 0001:02:00.0: reg 10: [mem 0xfffc0000-0xffffffff]
pci 0001:02:00.0: reg 14: [mem 0xfffc0000-0xffffffff]
pci 0001:02:00.0: calling pcibios_fixup_resources+0x0/0x238
pci 0001:02:00.0: calling quirk_resource_alignment+0x0/0x1c0
pci_bus 0001:02: fixups for bus
pci 0001:01:00.0: PCI bridge to [bus 02-ff]
pci 0001:01:00.0: bridge window [io 0x0000-0x0000] (disabled)
pci 0001:01:00.0: bridge window [mem 0x00000000-0x000fffff] (disabled)
pci 0001:01:00.0: bridge window [mem 0x00000000-0x000fffff pref]
(disabled)
irq: irq 1 on host /immr@e0000000/interrupt-controller@700 mapped to virtual
irq 16
__irq_set_trigger: setting type, irq = 16, flags = 8
ipic_set_irq_type function, with virq = 16, flow = 8
pci_bus 0001:02: bus scan returning with max=02
pci_bus 0001:01: bus scan returning with max=02
pci_bus 0002:03: scanning bus
pci_bus 0002:03: fixups for bus
pci_bus 0002:03: bus scan returning with max=03
PCI->OF bus map:
0 -> 0
1 -> 0
3 -> 0
PCI: Cannot allocate resource region 0 of device 0001:02:00.0, will remap
PCI: Cannot allocate resource region 1 of device 0001:02:00.0, will remap
pci 0001:01:00.0: BAR 8: assigned [mem 0xa8000000-0xa80fffff]
pci 0001:01:00.0: PCI bridge to [bus 02-02]
pci 0001:01:00.0: bridge window [io disabled]
pci 0001:01:00.0: bridge window [mem 0xa8000000-0xa80fffff]
pci 0001:01:00.0: bridge window [mem pref disabled]
pci_bus 0000:00: resource 0 [io 0x0000-0xfffff]
pci_bus 0000:00: resource 1 [mem 0x90000000-0x9fffffff]
pci_bus 0000:00: resource 2 [mem 0x80000000-0x8fffffff pref]
pci_bus 0001:01: resource 0 [io 0xff7fe000-0xffffdfff]
pci_bus 0001:01: resource 1 [mem 0xa8000000-0xb7ffffff]
pci_bus 0001:02: resource 1 [mem 0xa8000000-0xa80fffff]
pci_bus 0002:03: resource 0 [io 0xfeffc000-0xff7fbfff]
pci_bus 0002:03: resource 1 [mem 0xc8000000-0xd7ffffff]
Registering qe_ic with sysfs...
Registering ipic with sysfs...
bio: create slab <bio-0> at 0
vgaarb: loaded
SCSI subsystem initialized
Switching to clocksource timebase
NET: Registered protocol family 2
IP route cache hash table entries: 2048 (order: 1, 8192 bytes)
TCP established hash table entries: 8192 (order: 4, 65536 bytes)
TCP bind hash table entries: 8192 (order: 3, 32768 bytes)
TCP: Hash tables configured (established 8192 bind 8192)
TCP reno registered
UDP hash table entries: 256 (order: 0, 4096 bytes)
UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
NET: Registered protocol family 1
pci 0000:00:00.0: calling quirk_cardbus_legacy+0x0/0x44
pci 0000:00:00.0: calling quirk_usb_early_handoff+0x0/0x740
pci 0001:01:00.0: calling quirk_cardbus_legacy+0x0/0x44
pci 0001:01:00.0: calling quirk_usb_early_handoff+0x0/0x740
pci 0001:02:00.0: calling quirk_cardbus_legacy+0x0/0x44
pci 0001:02:00.0: calling quirk_usb_early_handoff+0x0/0x740
PCI: CLS 32 bytes, default 32
Trying to unpack rootfs image as initramfs...
rootfs image is not initramfs (no cpio magic); looks like an initrd
Freeing initrd memory: 3345k freed
irq: irq 9 on host /immr@e0000000/interrupt-controller@700 mapped to virtual
irq 17
__irq_set_trigger: setting type, irq = 17, flags = 8
ipic_set_irq_type function, with virq = 17, flow = 8
irq: irq 10 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 18
__irq_set_trigger: setting type, irq = 18, flags = 8
ipic_set_irq_type function, with virq = 18, flow = 8
irq: irq 80 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 80
__irq_set_trigger: setting type, irq = 80, flags = 8
ipic_set_irq_type function, with virq = 80, flow = 8
audit: initializing netlink socket (disabled)
type=2000 audit(0.212:1): initialized
JFFS2 version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
SGI XFS with security attributes, large block/inode numbers, no debug
enabled
msgmni has been set to 498
alg: No test for cipher_null (cipher_null-generic)
alg: No test for ecb(cipher_null) (ecb-cipher_null)
alg: No test for digest_null (digest_null-generic)
alg: No test for compress_null (compress_null-generic)
alg: No test for stdrng (krng)
Block layer SCSI generic (bsg) driver version 0.4 loaded (major 253)
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
serial8250.0: ttyS0 at MMIO 0xe0004500 (irq = 17) is a 16550A
console [ttyS0] enabled, bootconsole disabled
serial8250.0: ttyS1 at MMIO 0xe0004600 (irq = 18) is a 16550A
brd: module loaded
of_mpc8xxx_spi_probe function called.
irq: irq 16 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 19
__irq_set_trigger: setting type, irq = 19, flags = 8
ipic_set_irq_type function, with virq = 19, flow = 8
mpc8xxx_spi_probe function called.
mpc8xxx_spi e0007000.spi: at 0xd1078000 (irq = 19), CPU mode
irq: irq 32 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 32
__irq_set_trigger: setting type, irq = 32, flags = 8
ipic_set_irq_type function, with virq = 32, flow = 8
irq: irq 33 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 33
__irq_set_trigger: setting type, irq = 33, flags = 8
ipic_set_irq_type function, with virq = 33, flow = 8
irq: irq 34 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 34
__irq_set_trigger: setting type, irq = 34, flags = 8
ipic_set_irq_type function, with virq = 34, flow = 8
eth0: Gianfar Ethernet Controller Version 1.2, 04:00:00:00:00:0a
eth0: Running with NAPI enabled
eth0: RX BD ring size for Q[0]: 256
eth0: TX BD ring size for Q[0]: 256
irq: irq 35 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 35
__irq_set_trigger: setting type, irq = 35, flags = 8
ipic_set_irq_type function, with virq = 35, flow = 8
irq: irq 36 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 36
__irq_set_trigger: setting type, irq = 36, flags = 8
ipic_set_irq_type function, with virq = 36, flow = 8
irq: irq 37 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 37
__irq_set_trigger: setting type, irq = 37, flags = 8
ipic_set_irq_type function, with virq = 37, flow = 8
eth1: Gianfar Ethernet Controller Version 1.2, 00:00:00:00:00:00
eth1: Running with NAPI enabled
eth1: RX BD ring size for Q[0]: 256
eth1: TX BD ring size for Q[0]: 256
ucc_geth: QE UCC Gigabit Ethernet Controller
Freescale PowerQUICC MII Bus: probed
irq: irq 17 on host /immr@e0000000/interrupt-controller@700 mapped to
virtual irq 20
__irq_set_trigger: setting type, irq = 20, flags = 8
ipic_set_irq_type function, with virq = 20, flow = 8
Freescale PowerQUICC MII Bus: probed
mice: PS/2 mouse device common for all mice
Skipping unavailable LED gpio -19 (pwr)
Skipping unavailable LED gpio -19 (hdd)
TCP cubic registered
NET: Registered protocol family 17
registered taskstats version 1
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
RAMDISK: gzip image found at block 0
VFS: Mounted root (ext2 filesystem) on device 1:0.
Freeing unused kernel memory: 192k init
PHY: mdio@e0024520:02 - Link is Up - 10/Half
================================================================
Regards
Ravi Gupta
[-- Attachment #1.2: Type: text/html, Size: 18171 bytes --]
[-- Attachment #2: dmesg_log --]
[-- Type: application/octet-stream, Size: 12441 bytes --]
Using MPC837x RDB/WLAN machine description
Initializing cgroup subsys cpuset
Initializing cgroup subsys cpu
Linux version 2.6.35 (okapi@okapi) (gcc version 4.2.3 (Sourcery G++ Lite 4.2-171)) #13 Tue Sep 7 11:37:47 IST 2010
Found initrd at 0xcf46d000:0xcf7b15b7
Found legacy serial port 0 for /immr@e0000000/serial@4500
mem=e0004500, taddr=e0004500, irq=0, clk=399999996, speed=0
Found legacy serial port 1 for /immr@e0000000/serial@4600
mem=e0004600, taddr=e0004600, irq=0, clk=399999996, speed=0
bootconsole [udbg0] enabled
Found FSL PCI host bridge at 0x00000000e0008500. Firmware bus number: 0->0
PCI host bridge /pci@e0008500 (primary) ranges:
MEM 0x0000000090000000..0x000000009fffffff -> 0x0000000090000000
MEM 0x0000000080000000..0x000000008fffffff -> 0x0000000080000000 Prefetch
IO 0x00000000e0300000..0x00000000e03fffff -> 0x0000000000000000
No pci config register base in dev tree, using default
Found FSL PCI host bridge at 0x00000000e0009000. Firmware bus number: 0->255
PCI host bridge /pcie@e0009000 ranges:
MEM 0x00000000a8000000..0x00000000b7ffffff -> 0x00000000a8000000
IO 0x00000000b8000000..0x00000000b87fffff -> 0x0000000000000000
No pci config register base in dev tree, using default
Found FSL PCI host bridge at 0x00000000e000a000. Firmware bus number: 0->255
PCI host bridge /pcie@e000a000 ranges:
MEM 0x00000000c8000000..0x00000000d7ffffff -> 0x00000000c8000000
IO 0x00000000d8000000..0x00000000d87fffff -> 0x0000000000000000
Top of RAM: 0x10000000, Total RAM: 0x10000000
Memory hole size: 0MB
Zone PFN ranges:
DMA 0x00000000 -> 0x00010000
Normal empty
HighMem empty
Movable zone start PFN for each node
early_node_map[1] active PFN ranges
0: 0x00000000 -> 0x00010000
On node 0 totalpages: 65536
free_area_init_node: node 0, pgdat c04285e8, node_mem_map c0482000
DMA zone: 512 pages used for memmap
DMA zone: 0 pages reserved
DMA zone: 65024 pages, LIFO batch:15
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 65024
Kernel command line: root=/dev/ram ramdisk_size=120000 rw ip=10.20.50.230:10.20.50.70:10.20.50.50:255.255.0.0:PowerQUICC:eth0:off console=ttyS0,115200 mtdparts=nand:4m(kernel),-(jffs2)
PID hash table entries: 1024 (order: 0, 4096 bytes)
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
High memory: 0k
Memory: 251884k/262144k available (4072k kernel code, 10260k reserved, 244k data, 267k bss, 192k init)
Kernel virtual memory layout:
* 0xfffcf000..0xfffff000 : fixmap
* 0xff800000..0xffc00000 : highmem PTEs
* 0xfe6f7000..0xff800000 : early ioremap
* 0xd1000000..0xfe6f7000 : vmalloc & ioremap
Hierarchical RCU implementation.
RCU-based detection of stalled CPUs is disabled.
Verbose stalled-CPUs detection is disabled.
NR_IRQS:512
IPIC (128 IRQ sources) at d1000700
time_init: decrementer frequency = 99.999999 MHz
time_init: processor frequency = 799.999992 MHz
clocksource: timebase mult[2800000] shift[22] registered
clockevent: decrementer mult[19999995] shift[32] cpu[0]
Console: colour dummy device 80x25
pid_max: default: 32768 minimum: 301
Security Framework initialized
SELinux: Disabled at boot.
Mount-cache hash table entries: 512
Initializing cgroup subsys ns
Initializing cgroup subsys cpuacct
Initializing cgroup subsys devices
NET: Registered protocol family 16
irq: irq 38 on host /immr@e0000000/interrupt-controller@700 mapped to virtual irq 38
__irq_set_trigger: setting type, irq = 38, flags = 8
ipic_set_irq_type function, with virq = 38, flow = 8
irq: irq 74 on host /immr@e0000000/interrupt-controller@700 mapped to virtual irq 74
__irq_set_trigger: setting type, irq = 74, flags = 8
ipic_set_irq_type function, with virq = 74, flow = 8
irq: irq 75 on host /immr@e0000000/interrupt-controller@700 mapped to virtual irq 75
__irq_set_trigger: setting type, irq = 75, flags = 8
ipic_set_irq_type function, with virq = 75, flow = 8
PCI: Probing PCI hardware
pci_bus 0000:00: scanning bus
pci 0000:00:00.0: found [1957:00c6] class 000b20 header type 00
pci 0000:00:00.0: reg 10: [mem 0x00000000-0x000fffff]
pci 0000:00:00.0: reg 18: [mem 0x00000000-0x0fffffff 64bit pref]
pci 0000:00:00.0: calling fixup_hide_host_resource_fsl+0x0/0x58
pci 0000:00:00.0: calling pcibios_fixup_resources+0x0/0x238
pci 0000:00:00.0: calling quirk_fsl_pcie_header+0x0/0x48
pci 0000:00:00.0: calling quirk_resource_alignment+0x0/0x1c0
pci 0000:00:00.0: supports D1 D2
pci 0000:00:00.0: PME# supported from D0 D1 D2 D3hot
pci 0000:00:00.0: PME# disabled
pci_bus 0000:00: fixups for bus
pci_bus 0000:00: bus scan returning with max=00
pci_bus 0001:01: scanning bus
pci 0001:01:00.0: found [1957:00c6] class 000b20 header type 01
pci 0001:01:00.0: ignoring class b20 (doesn't match header type 01)
pci 0001:01:00.0: calling fixup_hide_host_resource_fsl+0x0/0x58
pci 0001:01:00.0: calling pcibios_fixup_resources+0x0/0x238
pci 0001:01:00.0: calling quirk_fsl_pcie_header+0x0/0x48
pci 0001:01:00.0: calling quirk_resource_alignment+0x0/0x1c0
pci 0001:01:00.0: supports D1 D2
pci 0001:01:00.0: PME# supported from D0 D1 D2 D3hot
pci 0001:01:00.0: PME# disabled
pci_bus 0001:01: fixups for bus
pci 0001:01:00.0: scanning [bus 01-ff] behind bridge, pass 0
pci 0001:01:00.0: bus configuration invalid, reconfiguring
pci 0001:01:00.0: scanning [bus 00-00] behind bridge, pass 1
pci_bus 0001:02: scanning bus
pci 0001:02:00.0: found [1204:e250] class 000000 header type 00
pci 0001:02:00.0: reg 10: [mem 0xfffc0000-0xffffffff]
pci 0001:02:00.0: reg 14: [mem 0xfffc0000-0xffffffff]
pci 0001:02:00.0: calling pcibios_fixup_resources+0x0/0x238
pci 0001:02:00.0: calling quirk_resource_alignment+0x0/0x1c0
pci_bus 0001:02: fixups for bus
pci 0001:01:00.0: PCI bridge to [bus 02-ff]
pci 0001:01:00.0: bridge window [io 0x0000-0x0000] (disabled)
pci 0001:01:00.0: bridge window [mem 0x00000000-0x000fffff] (disabled)
pci 0001:01:00.0: bridge window [mem 0x00000000-0x000fffff pref] (disabled)
irq: irq 1 on host /immr@e0000000/interrupt-controller@700 mapped to virtual irq 16
__irq_set_trigger: setting type, irq = 16, flags = 8
ipic_set_irq_type function, with virq = 16, flow = 8
pci_bus 0001:02: bus scan returning with max=02
pci_bus 0001:01: bus scan returning with max=02
pci_bus 0002:03: scanning bus
pci_bus 0002:03: fixups for bus
pci_bus 0002:03: bus scan returning with max=03
PCI->OF bus map:
0 -> 0
1 -> 0
3 -> 0
PCI: Cannot allocate resource region 0 of device 0001:02:00.0, will remap
PCI: Cannot allocate resource region 1 of device 0001:02:00.0, will remap
pci 0001:01:00.0: BAR 8: assigned [mem 0xa8000000-0xa80fffff]
pci 0001:01:00.0: PCI bridge to [bus 02-02]
pci 0001:01:00.0: bridge window [io disabled]
pci 0001:01:00.0: bridge window [mem 0xa8000000-0xa80fffff]
pci 0001:01:00.0: bridge window [mem pref disabled]
pci_bus 0000:00: resource 0 [io 0x0000-0xfffff]
pci_bus 0000:00: resource 1 [mem 0x90000000-0x9fffffff]
pci_bus 0000:00: resource 2 [mem 0x80000000-0x8fffffff pref]
pci_bus 0001:01: resource 0 [io 0xff7fe000-0xffffdfff]
pci_bus 0001:01: resource 1 [mem 0xa8000000-0xb7ffffff]
pci_bus 0001:02: resource 1 [mem 0xa8000000-0xa80fffff]
pci_bus 0002:03: resource 0 [io 0xfeffc000-0xff7fbfff]
pci_bus 0002:03: resource 1 [mem 0xc8000000-0xd7ffffff]
Registering qe_ic with sysfs...
Registering ipic with sysfs...
bio: create slab <bio-0> at 0
vgaarb: loaded
SCSI subsystem initialized
Switching to clocksource timebase
NET: Registered protocol family 2
IP route cache hash table entries: 2048 (order: 1, 8192 bytes)
TCP established hash table entries: 8192 (order: 4, 65536 bytes)
TCP bind hash table entries: 8192 (order: 3, 32768 bytes)
TCP: Hash tables configured (established 8192 bind 8192)
TCP reno registered
UDP hash table entries: 256 (order: 0, 4096 bytes)
UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
NET: Registered protocol family 1
pci 0000:00:00.0: calling quirk_cardbus_legacy+0x0/0x44
pci 0000:00:00.0: calling quirk_usb_early_handoff+0x0/0x740
pci 0001:01:00.0: calling quirk_cardbus_legacy+0x0/0x44
pci 0001:01:00.0: calling quirk_usb_early_handoff+0x0/0x740
pci 0001:02:00.0: calling quirk_cardbus_legacy+0x0/0x44
pci 0001:02:00.0: calling quirk_usb_early_handoff+0x0/0x740
PCI: CLS 32 bytes, default 32
Trying to unpack rootfs image as initramfs...
rootfs image is not initramfs (no cpio magic); looks like an initrd
Freeing initrd memory: 3345k freed
irq: irq 9 on host /immr@e0000000/interrupt-controller@700 mapped to virtual irq 17
__irq_set_trigger: setting type, irq = 17, flags = 8
ipic_set_irq_type function, with virq = 17, flow = 8
irq: irq 10 on host /immr@e0000000/interrupt-controller@700 mapped to virtual irq 18
__irq_set_trigger: setting type, irq = 18, flags = 8
ipic_set_irq_type function, with virq = 18, flow = 8
irq: irq 80 on host /immr@e0000000/interrupt-controller@700 mapped to virtual irq 80
__irq_set_trigger: setting type, irq = 80, flags = 8
ipic_set_irq_type function, with virq = 80, flow = 8
audit: initializing netlink socket (disabled)
type=2000 audit(0.212:1): initialized
JFFS2 version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
SGI XFS with security attributes, large block/inode numbers, no debug enabled
msgmni has been set to 498
alg: No test for cipher_null (cipher_null-generic)
alg: No test for ecb(cipher_null) (ecb-cipher_null)
alg: No test for digest_null (digest_null-generic)
alg: No test for compress_null (compress_null-generic)
alg: No test for stdrng (krng)
Block layer SCSI generic (bsg) driver version 0.4 loaded (major 253)
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
serial8250.0: ttyS0 at MMIO 0xe0004500 (irq = 17) is a 16550A
console [ttyS0] enabled, bootconsole disabled
serial8250.0: ttyS1 at MMIO 0xe0004600 (irq = 18) is a 16550A
brd: module loaded
of_mpc8xxx_spi_probe function called.
irq: irq 16 on host /immr@e0000000/interrupt-controller@700 mapped to virtual irq 19
__irq_set_trigger: setting type, irq = 19, flags = 8
ipic_set_irq_type function, with virq = 19, flow = 8
mpc8xxx_spi_probe function called.
mpc8xxx_spi e0007000.spi: at 0xd1078000 (irq = 19), CPU mode
irq: irq 32 on host /immr@e0000000/interrupt-controller@700 mapped to virtual irq 32
__irq_set_trigger: setting type, irq = 32, flags = 8
ipic_set_irq_type function, with virq = 32, flow = 8
irq: irq 33 on host /immr@e0000000/interrupt-controller@700 mapped to virtual irq 33
__irq_set_trigger: setting type, irq = 33, flags = 8
ipic_set_irq_type function, with virq = 33, flow = 8
irq: irq 34 on host /immr@e0000000/interrupt-controller@700 mapped to virtual irq 34
__irq_set_trigger: setting type, irq = 34, flags = 8
ipic_set_irq_type function, with virq = 34, flow = 8
eth0: Gianfar Ethernet Controller Version 1.2, 04:00:00:00:00:0a
eth0: Running with NAPI enabled
eth0: RX BD ring size for Q[0]: 256
eth0: TX BD ring size for Q[0]: 256
irq: irq 35 on host /immr@e0000000/interrupt-controller@700 mapped to virtual irq 35
__irq_set_trigger: setting type, irq = 35, flags = 8
ipic_set_irq_type function, with virq = 35, flow = 8
irq: irq 36 on host /immr@e0000000/interrupt-controller@700 mapped to virtual irq 36
__irq_set_trigger: setting type, irq = 36, flags = 8
ipic_set_irq_type function, with virq = 36, flow = 8
irq: irq 37 on host /immr@e0000000/interrupt-controller@700 mapped to virtual irq 37
__irq_set_trigger: setting type, irq = 37, flags = 8
ipic_set_irq_type function, with virq = 37, flow = 8
eth1: Gianfar Ethernet Controller Version 1.2, 00:00:00:00:00:00
eth1: Running with NAPI enabled
eth1: RX BD ring size for Q[0]: 256
eth1: TX BD ring size for Q[0]: 256
ucc_geth: QE UCC Gigabit Ethernet Controller
Freescale PowerQUICC MII Bus: probed
irq: irq 17 on host /immr@e0000000/interrupt-controller@700 mapped to virtual irq 20
__irq_set_trigger: setting type, irq = 20, flags = 8
ipic_set_irq_type function, with virq = 20, flow = 8
Freescale PowerQUICC MII Bus: probed
mice: PS/2 mouse device common for all mice
Skipping unavailable LED gpio -19 (pwr)
Skipping unavailable LED gpio -19 (hdd)
TCP cubic registered
NET: Registered protocol family 17
registered taskstats version 1
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
RAMDISK: gzip image found at block 0
VFS: Mounted root (ext2 filesystem) on device 1:0.
Freeing unused kernel memory: 192k init
PHY: mdio@e0024520:02 - Link is Up - 10/Half
^ permalink raw reply
* RE:
From: Rupjyoti Sarmah @ 2010-09-07 6:29 UTC (permalink / raw)
To: Wolfgang Denk; +Cc: linuxppc-dev, Prodyut Hazarika, Mark Miesfeld
In-Reply-To: <20100902061423.19D66153A79@gemini.denx.de>
Hi Wolfgang,
The current mainline 2.6.36-rc3 does not report any error while building
the SATA driver.
Regards,
Rup
-----Original Message-----
From: Rupjyoti Sarmah [mailto:rsarmah@apm.com]
Sent: Thursday, September 02, 2010 8:22 PM
To: 'Wolfgang Denk'
Cc: 'linuxppc-dev@ozlabs.org'; 'Prodyut Hazarika'; 'Mark Miesfeld'
Subject: RE:
Hi Wolfgang,
Sorry that I did not have a chance to check it recently.
Regards,
Rup
-----Original Message-----
From: Wolfgang Denk [mailto:wd@denx.de]
Sent: Thursday, September 02, 2010 11:44 AM
To: Rupjyoti Sarmah; Prodyut Hazarika; Mark Miesfeld
Cc: linuxppc-dev@ozlabs.org
Subject: Re:
Dear Rupjyoti, Prodyut, Mark,
two weeks ago I wrote:
In message <20100818205646.57783157D71@gemini.denx.de> you wrote:
>
> drivers/ata/sata_dwc_460ex.c fails to build in current mainline:
...
> Do you have any hints how to fix that?
Any comments or ideas how to fix this?
Best regards,
Wolfgang Denk
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
Time is an illusion perpetrated by the manufacturers of space.
^ permalink raw reply
* Re: pci_request_regions() failure
From: tiejun.chen @ 2010-09-07 5:25 UTC (permalink / raw)
To: Ravi Gupta; +Cc: linuxppc-dev
In-Reply-To: <AANLkTim5kasMWC6u-mhQyCRiPv1w7BCg7o-mBfy28DfS@mail.gmail.com>
Ravi Gupta wrote:
> Hi,
>
> I am facing a problem while requesting pci resource. I have some data that I
> am hopeful will help address the issue.
>
> I am currently running on a MPC837xERDB board(powerpc) with a 2.6.35 kernel.
> The problem is that whenever I insert the card (LatticeECP2M PCI Express
> Development Kit<http://www.latticesemi.com/products/developmenthardware/developmentkits/pciexpressdevkitecp2m/index.cfm>)
> in pci-express slot 0 and try to load my driver module, I get a
> pci_request_regions() failure(error -EBUSY). The interesting thing is the
> region that it fails for. According to /proc/iomem, slot0 has
> a8000000-b7ffffff as its memory ranges. However, the memory region requested
> by my device is a8000000-a803ffff and a8040000-a807ffff which falls in the
> slot0 range. But after boot up when I look at /proc/iomem, there is a
> already allocated resource range present there, which overlaps with the
> range refined in my device, hence the pci_request_regions() fails.
>
> Output of lspci
> 0000:00:00.0 Power PC: Freescale Semiconductor Inc Unknown device 00c6 (rev
> 21)
> 0001:01:00.0 PCI bridge: Freescale Semiconductor Inc Unknown device 00c6
> (rev 21)
> 0001:02:00.0 Non-VGA unclassified device: Lattice Semiconductor Corporation
> Unknown device e250 ---> My device
>
> Contents of /pro/iomem file
> # cat /proc/iomem
> 80000000-8fffffff : /pci@e0008500
> 90000000-9fffffff : /pci@e0008500
> a8000000-b7ffffff : /pcie@e0009000
> a8000000-a80fffff : PCI Bus 0001:02 ---> colprit range
> c8000000-d7ffffff : /pcie@e000a000
> e0004500-e0004507 : serial
> e0004600-e0004607 : serial
> e0023000-e0023fff : usb
>
> Now my doubt is, who is allocating this range and why? It seem to me a
I think the kernel don't allocate the used PCI range to another PCI device. So
you can enable CONFIG_PCI_DEBUG then execute 'dmesg' to get more information.
Before you don't load your module the kernel still can probe the plugged PCI
device and allocate/reserve appropriate PCI range for your device. Then you can
acquire the proper PCI IO/MEM range from there when loading device module. This
process should be transparent for the PCI device driver so I think this is
correct by '/proc/iomem'.
You can refer the following example on one PPC target.
Boot without enabling the given PCI device, e1000e.
------
c00000000-c1fffffff : /pcie@ffe200000
c00000000-c1fffffff : PCI Bus 0000:01
c00000000-c0001ffff : 0000:01:00.0
c00020000-c0003ffff : 0000:01:00.0
Boot with enable e1000e PCI device.
------
c00000000-c1fffffff : /pcie@ffe200000
c00000000-c1fffffff : PCI Bus 0000:01
c00000000-c0001ffff : 0000:01:00.0
c00000000-c0001ffff : e1000e
c00020000-c0003ffff : 0000:01:00.0
c00020000-c0003ffff : e1000e
So I think you can build your driver into the kernel to try again, or maybe you
should check your driver codes. Especially I want to know how/where you get
these two range, a8000000-a803ffff and a8040000-a807ffff. You wired them firstly
on the driver or allocated by the kernel?
Best Regards
Tiejun
> kernel bug as I also tried my device on i386 machine(opensuse, linux 2.6.35
> i.e the same kernel version on powerpc board) and there everything works
> fine. I don't know where to start to fix it. Please suggest.
>
> Output of lspci
>
> scooby:~ # lspci
> 00:00.0 Host bridge: Intel Corporation 82G33/G31/P35/P31 Express DRAM
> Controller (rev 10)
> 00:01.0 PCI bridge: Intel Corporation 82G33/G31/P35/P31 Express PCI Express
> Root Port (rev 10)
> 00:02.0 VGA compatible controller: Intel Corporation 82G33/G31 Express
> Integrated Graphics Controller (rev 10)
> 00:1b.0 Audio device: Intel Corporation 82801G (ICH7 Family) High Definition
> Audio Controller (rev 01)
> 00:1c.0 PCI bridge: Intel Corporation 82801G (ICH7 Family) PCI Express Port
> 1 (rev 01)
> 00:1c.1 PCI bridge: Intel Corporation 82801G (ICH7 Family) PCI Express Port
> 2 (rev 01)
> 00:1c.2 PCI bridge: Intel Corporation 82801G (ICH7 Family) PCI Express Port
> 3 (rev 01)
> 00:1d.0 USB Controller: Intel Corporation 82801G (ICH7 Family) USB UHCI
> Controller #1 (rev 01)
> 00:1d.1 USB Controller: Intel Corporation 82801G (ICH7 Family) USB UHCI
> Controller #2 (rev 01)
> 00:1d.2 USB Controller: Intel Corporation 82801G (ICH7 Family) USB UHCI
> Controller #3 (rev 01)
> 00:1d.3 USB Controller: Intel Corporation 82801G (ICH7 Family) USB UHCI
> Controller #4 (rev 01)
> 00:1d.7 USB Controller: Intel Corporation 82801G (ICH7 Family) USB2 EHCI
> Controller (rev 01)
> 00:1e.0 PCI bridge: Intel Corporation 82801 PCI Bridge (rev e1)
> 00:1f.0 ISA bridge: Intel Corporation 82801GB/GR (ICH7 Family) LPC Interface
> Bridge (rev 01)
> 00:1f.1 IDE interface: Intel Corporation 82801G (ICH7 Family) IDE Controller
> (rev 01)
> 00:1f.2 IDE interface: Intel Corporation 82801GB/GR/GH (ICH7 Family) SATA
> IDE Controller (rev 01)
> 00:1f.3 SMBus: Intel Corporation 82801G (ICH7 Family) SMBus Controller (rev
> 01)
> 03:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168B
> PCI Express Gigabit Ethernet controller (rev 01)
> 04:00.0 Non-VGA unclassified device: Lattice Semiconductor Corporation
> Device e250 ----------> My device
> 05:06.0 Serial controller: Device 4348:3253 (rev 10)
>
> Contents of /proc/iomem on i386 machine
>
> cat /proc/iomem
> .
> .
> .
> fe900000-fe9fffff : PCI Bus 0000:04
> fe900000-fe93ffff : 0000:04:00.0 ------------->My device
> fe940000-fe97ffff : 0000:04:00.0 ------------->My device
> fea00000-feafffff : PCI Bus 0000:03
> fea00000-fea1ffff : 0000:03:00.0
> fea20000-fea20fff : 0000:03:00.0
> fea20000-fea20fff : r8169
> .
> .
> .
>
> Regards,
>
> Ravi
>
>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH 1/2] drivers/net/fs_enet/fs_enet-main.c: Add of_node_put to avoid memory leak
From: David Miller @ 2010-09-07 1:29 UTC (permalink / raw)
To: julia
Cc: netdev, devicetree-discuss, kernel-janitors, linux-kernel,
vbordug, linuxppc-dev
In-Reply-To: <1283595164-29146-1-git-send-email-julia@diku.dk>
From: Julia Lawall <julia@diku.dk>
Date: Sat, 4 Sep 2010 12:12:43 +0200
> In this case, a device_node structure is stored in another structure that
> is then freed without first decrementing the reference count of the
> device_node structure.
>
> The semantic match that finds this problem is as follows:
> (http://coccinelle.lip6.fr/)
...
> Signed-off-by: Julia Lawall <julia@diku.dk>
Applied.
^ permalink raw reply
* Re: [v2 PATCH] ucc_geth: fix ethtool set ring param bug
From: David Miller @ 2010-09-06 20:22 UTC (permalink / raw)
To: liang.li; +Cc: netdev, avorontsov, linuxppc-dev
In-Reply-To: <1283443364-2136-1-git-send-email-liang.li@windriver.com>
From: Liang Li <liang.li@windriver.com>
Date: Fri, 3 Sep 2010 00:02:44 +0800
> + printk(KERN_INFO "Stopping interface %s.\n", netdev->name);
...
> + printk(KERN_INFO "Reactivating interface %s.\n", netdev->name);
Please get rid of these log messages.
Also, this isn't the way to implement this.
Abstract out the one and only operation that can fail when you change
the ring size, which is the memory allocations, into seperate code.
Allocate the newly sized rings first, and if that fails abort the
ring size change attempt. This will let the device continue to
function and operate properly even if the ring resizing fails.
Then stop the RX/TX DMA, switch the ring pointers and configuration
inside of the device, restart RX/TX DMA, and finally free up the
old ring memory.
I know why you want to use *_close() and *_open(), it requires less
coding and work on your part. But this is why the error handling
behavior is difficult and what happens on failure (device goes down
and becomes inoperative) is extremely unpleasant for the user.
The user should be able to make this kind of change over an SSH
shell that uses the interface itself, and not expect to lose
connectivity completely just because the ring allocation fails.
Thanks.
^ permalink raw reply
* Re: [PATCH 4/8] drivers/i2c/busses/i2c-pasemi.c: Fix unsigned return type
From: Olof Johansson @ 2010-09-06 16:30 UTC (permalink / raw)
To: Julia Lawall
Cc: kernel-janitors, linux-kernel, linux-i2c,
Ben Dooks (embedded platforms), Jean Delvare (PC drivers, core),
linuxppc-dev
In-Reply-To: <1283713226-8429-5-git-send-email-julia@diku.dk>
On Sun, Sep 05, 2010 at 09:00:22PM +0200, Julia Lawall wrote:
> The function has an unsigned return type, but returns a negative constant
> to indicate an error condition. The result of calling the function is
> always stored in a variable of type (signed) int, and thus unsigned can be
> dropped from the return type.
>
> A sematic match that finds this problem is as follows:
> (http://coccinelle.lip6.fr/)
>
> // <smpl>
> @exists@
> identifier f;
> constant C;
> @@
>
> unsigned f(...)
> { <+...
> * return -C;
> ...+> }
> // </smpl>
>
> Signed-off-by: Julia Lawall <julia@diku.dk>
Acked-by: Olof Johansson <olof@lixom.net>
^ permalink raw reply
* Re: [PATCH] APM821xx: Add support for new SoC APM821xx
From: Olof Johansson @ 2010-09-06 15:45 UTC (permalink / raw)
To: Tirumala Marri; +Cc: linuxppc-dev
In-Reply-To: <01bb9090932e6984c887273078fd586f@mail.gmail.com>
On Sun, Sep 05, 2010 at 10:19:53PM -0700, Tirumala Marri wrote:
> >
> > Then the device tree identifier, and the cpu setup functions, etc,
> > should indicate
> > 464, not APM821xx.
> This is new SoC based on 464 cpu core. All the previous SoC device tree
> CPU portion uses SoC name.
Hm, you're right. Confusing.
Still, the cpu setup functions would make more sense to have the core
name in, not the SoC name. Especially since multiple SoC families might
use the same core, etc.
> > Also, why add yet another defconfig? Isn't the eval board similar to
> > many others and can be supported with just a tweak of some existing
> > common defconfig instead?
> >
> Every new board needs new defconfig. And it is not same as others. It has
> Different features from other.
Actually, it doesn't. Linus has had a strong pushback to the ARM community
because of this mentality. arch/powerpc already has 100 defconfigs.
The use of devicetrees means that only the actual devices on your board,
will be configured, so it doesn't do any damage to compile in more drivers
than you happen to have. Thus generating a defconfig that is a superset
of some of your more common boards, or for example one per family of boards.
One of the arguments for having custom defconfigs per board is that customers that
base designs off of your eval board needs them. But they will make other changes
to the config to add drivers for whatever additional devices they have anyway.
-Olof
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox