* [PATCH fpga 7/9] fpga zynq: Use the scatterlist interface
From: Jason Gunthorpe @ 2016-11-09 22:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478732303-13718-1-git-send-email-jgunthorpe@obsidianresearch.com>
This allows the driver to avoid a high order coherent DMA allocation
and memory copy. With this patch it can DMA directly from the kernel
pages that the bitfile is stored in.
Since this is now a gather DMA operation the driver uses the ISR
to feed the chips DMA queue with each entry from the SGL.
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
---
drivers/fpga/zynq-fpga.c | 194 +++++++++++++++++++++++++++++++++++------------
1 file changed, 146 insertions(+), 48 deletions(-)
diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c
index ac2deae92dbd..559b4f2ab9f6 100644
--- a/drivers/fpga/zynq-fpga.c
+++ b/drivers/fpga/zynq-fpga.c
@@ -30,6 +30,7 @@
#include <linux/pm.h>
#include <linux/regmap.h>
#include <linux/string.h>
+#include <linux/scatterlist.h>
/* Offsets into SLCR regmap */
@@ -80,6 +81,7 @@
/* FPGA init status */
#define STATUS_DMA_Q_F BIT(31)
+#define STATUS_DMA_Q_E BIT(30)
#define STATUS_PCFG_INIT_MASK BIT(4)
/* Interrupt Status/Mask Register Bit definitions */
@@ -98,12 +100,14 @@
#define DMA_INVALID_ADDRESS GENMASK(31, 0)
/* Used to unlock the dev */
#define UNLOCK_MASK 0x757bdf0d
-/* Timeout for DMA to complete */
-#define DMA_DONE_TIMEOUT msecs_to_jiffies(1000)
/* Timeout for polling reset bits */
#define INIT_POLL_TIMEOUT 2500000
/* Delay for polling reset bits */
#define INIT_POLL_DELAY 20
+/* Signal this is the last DMA transfer, wait for the AXI and PCAP before
+ * interrupting
+ */
+#define DMA_SRC_LAST_TRANSFER 1
/* Masks for controlling stuff in SLCR */
/* Disable all Level shifters */
@@ -124,6 +128,11 @@ struct zynq_fpga_priv {
void __iomem *io_base;
struct regmap *slcr;
+ spinlock_t dma_lock;
+ unsigned int dma_elm;
+ unsigned int dma_nelms;
+ struct scatterlist *cur_sg;
+
struct completion dma_done;
};
@@ -149,15 +158,81 @@ static inline void zynq_fpga_set_irq_mask(struct zynq_fpga_priv *priv,
zynq_fpga_write(priv, INT_MASK_OFFSET, ~enable);
}
+/* Must be called with dma_lock held */
+static void zynq_step_dma(struct zynq_fpga_priv *priv)
+{
+ u32 addr;
+ u32 len;
+ bool first;
+
+ first = priv->dma_elm == 0;
+ while (priv->cur_sg) {
+ /* Feed the DMA queue until it is full. */
+ if (zynq_fpga_read(priv, STATUS_OFFSET) & STATUS_DMA_Q_F)
+ break;
+
+ addr = sg_dma_address(priv->cur_sg);
+ len = sg_dma_len(priv->cur_sg);
+ if (priv->dma_elm + 1 == priv->dma_nelms) {
+ /* The last transfer waits for the PCAP to finish too,
+ * notice this also changes the irq_mask to ignore
+ * IXR_DMA_DONE_MASK which ensures we do not trigger
+ * the completion too early.
+ */
+ addr |= DMA_SRC_LAST_TRANSFER;
+ priv->cur_sg = NULL;
+ } else {
+ priv->cur_sg = sg_next(priv->cur_sg);
+ priv->dma_elm++;
+ }
+
+ zynq_fpga_write(priv, DMA_SRC_ADDR_OFFSET, addr);
+ zynq_fpga_write(priv, DMA_DST_ADDR_OFFSET, DMA_INVALID_ADDRESS);
+ zynq_fpga_write(priv, DMA_SRC_LEN_OFFSET, len / 4);
+ zynq_fpga_write(priv, DMA_DEST_LEN_OFFSET, 0);
+ }
+
+ /* Once the first transfer is queued we can turn on the ISR, future
+ * calls to zynq_step_dma will happen from the ISR context. The
+ * dma_lock spinlock guarentees this handover is done coherently, the
+ * ISR enable is put at the end to avoid another CPU spinning in the
+ * ISR on this lock.
+ */
+ if (first && priv->cur_sg) {
+ zynq_fpga_set_irq_mask(priv, IXR_DMA_DONE_MASK |
+ IXR_ERROR_FLAGS_MASK);
+ } else if (!priv->cur_sg) {
+ /* The last transfer changes to DMA & PCAP mode since we do
+ * not want to continue until everything has bee flushed into
+ * the PCAP.
+ */
+ zynq_fpga_set_irq_mask(priv, IXR_D_P_DONE_MASK |
+ IXR_ERROR_FLAGS_MASK);
+ }
+}
+
static irqreturn_t zynq_fpga_isr(int irq, void *data)
{
struct zynq_fpga_priv *priv = data;
+ u32 intr_status;
- /* disable DMA and error IRQs */
- zynq_fpga_set_irq_mask(priv, 0);
+ /* If anything other than DMA completion is reported stop and hand
+ * control back to zynq_fpga_ops_write, something went wrong,
+ * otherwise progress the DMA.
+ */
+ spin_lock(&priv->dma_lock);
+ intr_status = zynq_fpga_read(priv, INT_STS_OFFSET);
+ if ((intr_status & IXR_ERROR_FLAGS_MASK) == 0 &&
+ (intr_status & IXR_DMA_DONE_MASK) && priv->cur_sg) {
+ zynq_fpga_write(priv, INT_STS_OFFSET, IXR_DMA_DONE_MASK);
+ zynq_step_dma(priv);
+ spin_unlock(&priv->dma_lock);
+ return IRQ_HANDLED;
+ }
+ spin_unlock(&priv->dma_lock);
+ zynq_fpga_set_irq_mask(priv, 0);
complete(&priv->dma_done);
-
return IRQ_HANDLED;
}
@@ -165,31 +240,47 @@ static irqreturn_t zynq_fpga_isr(int irq, void *data)
* the correct byte order. The input is a Xilinx .bin file with every 32 bit
* quantity swapped.
*/
-static bool zynq_fpga_has_sync(const char *buf, size_t count)
+static bool zynq_fpga_has_sync(struct sg_table *sgt)
{
- for (; count > 4; buf += 4, count -= 4)
- if (buf[0] == 0x66 && buf[1] == 0x55 && buf[2] == 0x99 &&
- buf[3] == 0xaa)
- return true;
+ struct sg_mapping_iter miter;
+ const u8 *buf, *end;
+
+ sg_miter_start(&miter, sgt->sgl, sgt->nents, SG_MITER_FROM_SG);
+
+ while (sg_miter_next(&miter)) {
+ end = miter.addr + miter.length;
+ for (buf = miter.addr; buf < end; buf += 4) {
+ if (buf[0] == 0x66 && buf[1] == 0x55 &&
+ buf[2] == 0x99 && buf[3] == 0xaa) {
+ sg_miter_stop(&miter);
+ return true;
+ }
+ }
+ }
+
+ sg_miter_stop(&miter);
return false;
}
static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
- const char *buf, size_t count)
+ struct sg_table *sgt)
{
struct zynq_fpga_priv *priv;
+ struct scatterlist *sg;
u32 ctrl, status;
- int err;
+ int err, i;
priv = mgr->priv;
- /* The hardware can only DMA multiples of 4 bytes, and we need at
- * least the sync word and something else to do anything.
+ /* The hardware can only DMA multiples of 4 bytes, and it requires the
+ * starting address to be aligned to 64 bits (UG585 pg 212).
*/
- if (count <= 4 || (count % 4) != 0) {
- dev_err(&mgr->dev,
- "Invalid bitstream size, must be multiples of 4 bytes\n");
- return -EINVAL;
+ for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+ if ((sg->offset % 8) != 0 || (sg->length % 4) != 0) {
+ dev_err(&mgr->dev,
+ "Invalid bitstream size, chunks must be aligned\n");
+ return -EINVAL;
+ }
}
err = clk_enable(priv->clk);
@@ -198,7 +289,7 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
/* don't globally reset PL if we're doing partial reconfig */
if (!(flags & FPGA_MGR_PARTIAL_RECONFIG)) {
- if (!zynq_fpga_has_sync(buf, count)) {
+ if (!zynq_fpga_has_sync(sgt)) {
dev_err(&mgr->dev,
"Invalid bitstream, could not find a sync word. Bitstream must be a byte swaped .bin file\n");
err = -EINVAL;
@@ -274,10 +365,11 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
zynq_fpga_write(priv, CTRL_OFFSET,
(CTRL_PCAP_PR_MASK | CTRL_PCAP_MODE_MASK | ctrl));
- /* check that we have room in the command queue */
+ /* We expect that the command queue is empty right now. */
status = zynq_fpga_read(priv, STATUS_OFFSET);
- if (status & STATUS_DMA_Q_F) {
- dev_err(&mgr->dev, "DMA command queue full\n");
+ if ((status & STATUS_DMA_Q_F) ||
+ (status & STATUS_DMA_Q_E) != STATUS_DMA_Q_E) {
+ dev_err(&mgr->dev, "DMA command queue not right\n");
err = -EBUSY;
goto out_err;
}
@@ -296,49 +388,50 @@ out_err:
return err;
}
-static int zynq_fpga_ops_write(struct fpga_manager *mgr,
- const char *buf, size_t count)
+static int zynq_fpga_ops_write(struct fpga_manager *mgr, struct sg_table *sgt)
{
struct zynq_fpga_priv *priv;
const char *why;
int err;
- char *kbuf;
- dma_addr_t dma_addr;
u32 intr_status;
+ unsigned long timeout;
+ unsigned long flags;
priv = mgr->priv;
- kbuf =
- dma_alloc_coherent(mgr->dev.parent, count, &dma_addr, GFP_KERNEL);
- if (!kbuf)
+ priv->dma_nelms =
+ dma_map_sg(mgr->dev.parent, sgt->sgl, sgt->nents, DMA_TO_DEVICE);
+ if (priv->dma_nelms == 0)
return -ENOMEM;
- memcpy(kbuf, buf, count);
-
/* enable clock */
err = clk_enable(priv->clk);
if (err)
goto out_free;
zynq_fpga_write(priv, INT_STS_OFFSET, IXR_ALL_MASK);
-
reinit_completion(&priv->dma_done);
- /* enable DMA and error IRQs */
- zynq_fpga_set_irq_mask(priv, IXR_D_P_DONE_MASK | IXR_ERROR_FLAGS_MASK);
+ /* zynq_step_dma will turn on interrupts */
+ spin_lock_irqsave(&priv->dma_lock, flags);
+ priv->dma_elm = 0;
+ priv->cur_sg = sgt->sgl;
+ zynq_step_dma(priv);
+ spin_unlock_irqrestore(&priv->dma_lock, flags);
- /* the +1 in the src addr is used to hold off on DMA_DONE IRQ
- * until both AXI and PCAP are done ...
- */
- zynq_fpga_write(priv, DMA_SRC_ADDR_OFFSET, (u32)(dma_addr) + 1);
- zynq_fpga_write(priv, DMA_DST_ADDR_OFFSET, (u32)DMA_INVALID_ADDRESS);
- zynq_fpga_write(priv, DMA_SRC_LEN_OFFSET, count / 4);
- zynq_fpga_write(priv, DMA_DEST_LEN_OFFSET, 0);
+ timeout = wait_for_completion_timeout(&priv->dma_done,
+ msecs_to_jiffies(5 * 1000));
- wait_for_completion(&priv->dma_done);
+ zynq_fpga_set_irq_mask(priv, 0);
intr_status = zynq_fpga_read(priv, INT_STS_OFFSET);
- zynq_fpga_write(priv, INT_STS_OFFSET, intr_status);
+ zynq_fpga_write(priv, INT_STS_OFFSET, IXR_ALL_MASK);
+
+ /* There doesn't seem to be a way to force cancel any DMA, so if
+ * something went wrong we are relying on the hardware to have halted
+ * the DMA before we get here, if there was we could use
+ * wait_for_completion_interruptible too.
+ */
if (intr_status & IXR_ERROR_FLAGS_MASK) {
why = "DMA reported error";
@@ -346,8 +439,12 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr,
goto out_report;
}
- if (!((intr_status & IXR_D_P_DONE_MASK) == IXR_D_P_DONE_MASK)) {
- why = "DMA did not complete";
+ if (priv->cur_sg ||
+ !((intr_status & IXR_D_P_DONE_MASK) == IXR_D_P_DONE_MASK)) {
+ if (timeout == 0)
+ why = "DMA timed out";
+ else
+ why = "DMA did not complete";
err = -EIO;
goto out_report;
}
@@ -368,7 +465,7 @@ out_report:
out_clk:
clk_disable(priv->clk);
out_free:
- dma_free_coherent(mgr->dev.parent, count, kbuf, dma_addr);
+ dma_unmap_sg(mgr->dev.parent, sgt->sgl, sgt->nents, DMA_TO_DEVICE);
return err;
}
@@ -429,8 +526,8 @@ static enum fpga_mgr_states zynq_fpga_ops_state(struct fpga_manager *mgr)
static const struct fpga_manager_ops zynq_fpga_ops = {
.state = zynq_fpga_ops_state,
- .write_init = zynq_fpga_ops_write_init,
- .write = zynq_fpga_ops_write,
+ .write_init_sg = zynq_fpga_ops_write_init,
+ .write_sg = zynq_fpga_ops_write,
.write_complete = zynq_fpga_ops_write_complete,
};
@@ -444,6 +541,7 @@ static int zynq_fpga_probe(struct platform_device *pdev)
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
+ spin_lock_init(&priv->dma_lock);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->io_base = devm_ioremap_resource(dev, res);
--
2.1.4
^ permalink raw reply related
* [PATCH fpga 6/9] fpga: Add scatterlist based write ops to the driver ops
From: Jason Gunthorpe @ 2016-11-09 22:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478732303-13718-1-git-send-email-jgunthorpe@obsidianresearch.com>
Requiring contiguous kernel memory is not a good idea, this is a limited
resource and allocation can fail under normal work loads.
As a first step allow for drivers to provide a _sg write interface and
internally convert the existing contiguous mappings into a scatterlist.
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
---
drivers/fpga/fpga-mgr.c | 127 +++++++++++++++++++++++++++++++++++++++---
include/linux/fpga/fpga-mgr.h | 9 ++-
2 files changed, 128 insertions(+), 8 deletions(-)
diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c
index 953dc9195937..c2491ffeabd3 100644
--- a/drivers/fpga/fpga-mgr.c
+++ b/drivers/fpga/fpga-mgr.c
@@ -25,26 +25,76 @@
#include <linux/of.h>
#include <linux/mutex.h>
#include <linux/slab.h>
+#include <linux/scatterlist.h>
+#include <linux/highmem.h>
static DEFINE_IDA(fpga_mgr_ida);
static struct class *fpga_mgr_class;
/**
- * fpga_mgr_buf_load - load fpga from image in buffer
+ * fpga_mgr_buf_load_sg - load fpga from image in buffer from a scatter list
* @mgr: fpga manager
* @flags: flags setting fpga confuration modes
- * @buf: buffer contain fpga image
- * @count: byte count of buf
+ * @sgt: scatterlist table
*
* Step the low level fpga manager through the device-specific steps of getting
* an FPGA ready to be configured, writing the image to it, then doing whatever
* post-configuration steps necessary. This code assumes the caller got the
* mgr pointer from of_fpga_mgr_get() and checked that it is not an error code.
*
+ * This is the preferred entry point for FPGA programming, it does not require
+ * any contiguous kernel memory.
+ *
* Return: 0 on success, negative error code otherwise.
*/
-int fpga_mgr_buf_load(struct fpga_manager *mgr, u32 flags, const char *buf,
- size_t count)
+static int fpga_mgr_buf_load_sg(struct fpga_manager *mgr, u32 flags,
+ struct sg_table *sgt)
+{
+ struct device *dev = &mgr->dev;
+ int ret;
+
+ /*
+ * Call the low level driver's write_init function. This will do the
+ * device-specific things to get the FPGA into the state where it is
+ * ready to receive an FPGA image.
+ */
+ mgr->state = FPGA_MGR_STATE_WRITE_INIT;
+ ret = mgr->mops->write_init_sg(mgr, flags, sgt);
+ if (ret) {
+ dev_err(dev, "Error preparing FPGA for writing\n");
+ mgr->state = FPGA_MGR_STATE_WRITE_INIT_ERR;
+ return ret;
+ }
+
+ /*
+ * Write the FPGA image to the FPGA.
+ */
+ mgr->state = FPGA_MGR_STATE_WRITE;
+ ret = mgr->mops->write_sg(mgr, sgt);
+ if (ret) {
+ dev_err(dev, "Error while writing image data to FPGA\n");
+ mgr->state = FPGA_MGR_STATE_WRITE_ERR;
+ return ret;
+ }
+
+ /*
+ * After all the FPGA image has been written, do the device specific
+ * steps to finish and set the FPGA into operating mode.
+ */
+ mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE;
+ ret = mgr->mops->write_complete(mgr, flags);
+ if (ret) {
+ dev_err(dev, "Error after writing image data to FPGA\n");
+ mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE_ERR;
+ return ret;
+ }
+ mgr->state = FPGA_MGR_STATE_OPERATING;
+
+ return 0;
+}
+
+static int fpga_mgr_buf_load_mapped(struct fpga_manager *mgr, u32 flags,
+ const char *buf, size_t count)
{
struct device *dev = &mgr->dev;
int ret;
@@ -88,6 +138,68 @@ int fpga_mgr_buf_load(struct fpga_manager *mgr, u32 flags, const char *buf,
return 0;
}
+
+/**
+ * fpga_mgr_buf_load - load fpga from image in buffer
+ * @mgr: fpga manager
+ * @flags: flags setting fpga confuration modes
+ * @buf: buffer contain fpga image
+ * @count: byte count of buf
+ *
+ * Step the low level fpga manager through the device-specific steps of getting
+ * an FPGA ready to be configured, writing the image to it, then doing whatever
+ * post-configuration steps necessary. This code assumes the caller got the
+ * mgr pointer from of_fpga_mgr_get() and checked that it is not an error code.
+ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+int fpga_mgr_buf_load(struct fpga_manager *mgr, u32 flags, const char *buf,
+ size_t count)
+{
+ struct page **pages;
+ struct sg_table sgt;
+ const void *p;
+ int nr_pages;
+ int index;
+ int rc;
+
+ if (!mgr->mops->write_init_sg || !mgr->mops->write_sg)
+ return fpga_mgr_buf_load_mapped(mgr, flags, buf, count);
+
+ /*
+ * Convert the linear kernel pointer into a sg_table of pages for use
+ * by the driver.
+ */
+ nr_pages = DIV_ROUND_UP((unsigned long)buf + count, PAGE_SIZE) -
+ (unsigned long)buf / PAGE_SIZE;
+ pages = kmalloc_array(nr_pages, sizeof(struct page *), GFP_KERNEL);
+ if (!pages)
+ return -ENOMEM;
+
+ p = (buf - offset_in_page(p));
+ for (index = 0; index < nr_pages; index++) {
+ if (is_vmalloc_addr(p))
+ pages[index] = vmalloc_to_page(p);
+ else
+ pages[index] = kmap_to_page((void *)p);
+ p += PAGE_SIZE;
+ }
+
+ /*
+ * The temporary pages list is used to code share the merging algorithm
+ * in sg_alloc_table_from_pages
+ */
+ rc = sg_alloc_table_from_pages(&sgt, pages, index, offset_in_page(buf),
+ count, GFP_KERNEL);
+ kfree(pages);
+ if (rc)
+ return rc;
+
+ rc = fpga_mgr_buf_load_sg(mgr, flags, &sgt);
+ sg_free_table(&sgt);
+
+ return rc;
+}
EXPORT_SYMBOL_GPL(fpga_mgr_buf_load);
/**
@@ -256,8 +368,9 @@ int fpga_mgr_register(struct device *dev, const char *name,
struct fpga_manager *mgr;
int id, ret;
- if (!mops || !mops->write_init || !mops->write ||
- !mops->write_complete || !mops->state) {
+ if (!mops || !mops->write_complete || !mops->state ||
+ ((!mops->write_init || !mops->write) &&
+ (!mops->write_init_sg || !mops->write_sg))) {
dev_err(dev, "Attempt to register without fpga_manager_ops\n");
return -EINVAL;
}
diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h
index 0940bf45e2f2..371b30ea60eb 100644
--- a/include/linux/fpga/fpga-mgr.h
+++ b/include/linux/fpga/fpga-mgr.h
@@ -22,6 +22,7 @@
#define _LINUX_FPGA_MGR_H
struct fpga_manager;
+struct sg_table;
/**
* enum fpga_mgr_states - fpga framework states
@@ -71,8 +72,11 @@ enum fpga_mgr_states {
/**
* struct fpga_manager_ops - ops for low level fpga manager drivers
* @state: returns an enum value of the FPGA's state
- * @write_init: prepare the FPGA to receive confuration data
+ * @write_init: prepare the FPGA to receive confuration data (linear memory)
* @write: write count bytes of configuration data to the FPGA
+ * @write_init_sg: prepare the FPGA to receive confuration data (scatter list
+ * table)
+ * @write_sg: write count bytes of configuration data to the FPGA
* @write_complete: set FPGA to operating state after writing is done
* @fpga_remove: optional: Set FPGA into a specific state during driver remove
*
@@ -85,6 +89,9 @@ struct fpga_manager_ops {
int (*write_init)(struct fpga_manager *mgr, u32 flags,
const char *buf, size_t count);
int (*write)(struct fpga_manager *mgr, const char *buf, size_t count);
+ int (*write_init_sg)(struct fpga_manager *mgr, u32 flags,
+ struct sg_table *sgt);
+ int (*write_sg)(struct fpga_manager *mgr, struct sg_table *sgt);
int (*write_complete)(struct fpga_manager *mgr, u32 flags);
void (*fpga_remove)(struct fpga_manager *mgr);
};
--
2.1.4
^ permalink raw reply related
* [PATCH fpga 5/9] fpga zynq: Remove priv->dev
From: Jason Gunthorpe @ 2016-11-09 22:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478732303-13718-1-git-send-email-jgunthorpe@obsidianresearch.com>
socfpga uses mgr->dev for debug prints, there should be consistency
here, so standardize on that. The only other use was for dma
which can be replaced with mgr->dev.parent.
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
---
drivers/fpga/zynq-fpga.c | 22 ++++++++++------------
1 file changed, 10 insertions(+), 12 deletions(-)
diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c
index 3ffc5fcc3072..ac2deae92dbd 100644
--- a/drivers/fpga/zynq-fpga.c
+++ b/drivers/fpga/zynq-fpga.c
@@ -118,7 +118,6 @@
#define FPGA_RST_NONE_MASK 0x0
struct zynq_fpga_priv {
- struct device *dev;
int irq;
struct clk *clk;
@@ -188,7 +187,7 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
* least the sync word and something else to do anything.
*/
if (count <= 4 || (count % 4) != 0) {
- dev_err(priv->dev,
+ dev_err(&mgr->dev,
"Invalid bitstream size, must be multiples of 4 bytes\n");
return -EINVAL;
}
@@ -200,7 +199,7 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
/* don't globally reset PL if we're doing partial reconfig */
if (!(flags & FPGA_MGR_PARTIAL_RECONFIG)) {
if (!zynq_fpga_has_sync(buf, count)) {
- dev_err(priv->dev,
+ dev_err(&mgr->dev,
"Invalid bitstream, could not find a sync word. Bitstream must be a byte swaped .bin file\n");
err = -EINVAL;
goto out_err;
@@ -233,7 +232,7 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
INIT_POLL_DELAY,
INIT_POLL_TIMEOUT);
if (err) {
- dev_err(priv->dev, "Timeout waiting for PCFG_INIT\n");
+ dev_err(&mgr->dev, "Timeout waiting for PCFG_INIT\n");
goto out_err;
}
@@ -247,7 +246,7 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
INIT_POLL_DELAY,
INIT_POLL_TIMEOUT);
if (err) {
- dev_err(priv->dev, "Timeout waiting for !PCFG_INIT\n");
+ dev_err(&mgr->dev, "Timeout waiting for !PCFG_INIT\n");
goto out_err;
}
@@ -261,7 +260,7 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
INIT_POLL_DELAY,
INIT_POLL_TIMEOUT);
if (err) {
- dev_err(priv->dev, "Timeout waiting for PCFG_INIT\n");
+ dev_err(&mgr->dev, "Timeout waiting for PCFG_INIT\n");
goto out_err;
}
}
@@ -278,7 +277,7 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
/* check that we have room in the command queue */
status = zynq_fpga_read(priv, STATUS_OFFSET);
if (status & STATUS_DMA_Q_F) {
- dev_err(priv->dev, "DMA command queue full\n");
+ dev_err(&mgr->dev, "DMA command queue full\n");
err = -EBUSY;
goto out_err;
}
@@ -309,7 +308,8 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr,
priv = mgr->priv;
- kbuf = dma_alloc_coherent(priv->dev, count, &dma_addr, GFP_KERNEL);
+ kbuf =
+ dma_alloc_coherent(mgr->dev.parent, count, &dma_addr, GFP_KERNEL);
if (!kbuf)
return -ENOMEM;
@@ -356,7 +356,7 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr,
goto out_clk;
out_report:
- dev_err(priv->dev,
+ dev_err(&mgr->dev,
"%s: INT_STS:0x%x CTRL:0x%x LOCK:0x%x INT_MASK:0x%x STATUS:0x%x MCTRL:0x%x\n",
why,
intr_status,
@@ -368,7 +368,7 @@ out_report:
out_clk:
clk_disable(priv->clk);
out_free:
- dma_free_coherent(priv->dev, count, kbuf, dma_addr);
+ dma_free_coherent(mgr->dev.parent, count, kbuf, dma_addr);
return err;
}
@@ -445,8 +445,6 @@ static int zynq_fpga_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
- priv->dev = dev;
-
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->io_base = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->io_base))
--
2.1.4
^ permalink raw reply related
* [PATCH fpga 4/9] fpga zynq: Check for errors after completing DMA
From: Jason Gunthorpe @ 2016-11-09 22:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478732303-13718-1-git-send-email-jgunthorpe@obsidianresearch.com>
The completion did not check the interrupt status to see if any error
bits were asserted, check error bits and dump some registers if things
went wrong.
A few fixes are needed to make this work, the IXR_ERROR_FLAGS_MASK was
wrong, it included the done bits, which shows a bug in mask/unmask_irqs
which were using the wrong bits, simplify all of this stuff.
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
---
drivers/fpga/zynq-fpga.c | 55 +++++++++++++++++++++++++++---------------------
1 file changed, 31 insertions(+), 24 deletions(-)
diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c
index 40cf0feaca7c..3ffc5fcc3072 100644
--- a/drivers/fpga/zynq-fpga.c
+++ b/drivers/fpga/zynq-fpga.c
@@ -89,7 +89,7 @@
#define IXR_D_P_DONE_MASK BIT(12)
/* FPGA programmed */
#define IXR_PCFG_DONE_MASK BIT(2)
-#define IXR_ERROR_FLAGS_MASK 0x00F0F860
+#define IXR_ERROR_FLAGS_MASK 0x00F0C860
#define IXR_ALL_MASK 0xF8F7F87F
/* Miscellaneous constant values */
@@ -144,23 +144,10 @@ static inline u32 zynq_fpga_read(const struct zynq_fpga_priv *priv,
readl_poll_timeout(priv->io_base + addr, val, cond, sleep_us, \
timeout_us)
-static void zynq_fpga_mask_irqs(struct zynq_fpga_priv *priv)
+static inline void zynq_fpga_set_irq_mask(struct zynq_fpga_priv *priv,
+ u32 enable)
{
- u32 intr_mask;
-
- intr_mask = zynq_fpga_read(priv, INT_MASK_OFFSET);
- zynq_fpga_write(priv, INT_MASK_OFFSET,
- intr_mask | IXR_DMA_DONE_MASK | IXR_ERROR_FLAGS_MASK);
-}
-
-static void zynq_fpga_unmask_irqs(struct zynq_fpga_priv *priv)
-{
- u32 intr_mask;
-
- intr_mask = zynq_fpga_read(priv, INT_MASK_OFFSET);
- zynq_fpga_write(priv, INT_MASK_OFFSET,
- intr_mask
- & ~(IXR_D_P_DONE_MASK | IXR_ERROR_FLAGS_MASK));
+ zynq_fpga_write(priv, INT_MASK_OFFSET, ~enable);
}
static irqreturn_t zynq_fpga_isr(int irq, void *data)
@@ -168,7 +155,7 @@ static irqreturn_t zynq_fpga_isr(int irq, void *data)
struct zynq_fpga_priv *priv = data;
/* disable DMA and error IRQs */
- zynq_fpga_mask_irqs(priv);
+ zynq_fpga_set_irq_mask(priv, 0);
complete(&priv->dma_done);
@@ -314,6 +301,7 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr,
const char *buf, size_t count)
{
struct zynq_fpga_priv *priv;
+ const char *why;
int err;
char *kbuf;
dma_addr_t dma_addr;
@@ -337,7 +325,7 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr,
reinit_completion(&priv->dma_done);
/* enable DMA and error IRQs */
- zynq_fpga_unmask_irqs(priv);
+ zynq_fpga_set_irq_mask(priv, IXR_D_P_DONE_MASK | IXR_ERROR_FLAGS_MASK);
/* the +1 in the src addr is used to hold off on DMA_DONE IRQ
* until both AXI and PCAP are done ...
@@ -352,16 +340,35 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr,
intr_status = zynq_fpga_read(priv, INT_STS_OFFSET);
zynq_fpga_write(priv, INT_STS_OFFSET, intr_status);
+ if (intr_status & IXR_ERROR_FLAGS_MASK) {
+ why = "DMA reported error";
+ err = -EIO;
+ goto out_report;
+ }
+
if (!((intr_status & IXR_D_P_DONE_MASK) == IXR_D_P_DONE_MASK)) {
- dev_err(priv->dev, "Error configuring FPGA\n");
- err = -EFAULT;
+ why = "DMA did not complete";
+ err = -EIO;
+ goto out_report;
}
+ err = 0;
+ goto out_clk;
+
+out_report:
+ dev_err(priv->dev,
+ "%s: INT_STS:0x%x CTRL:0x%x LOCK:0x%x INT_MASK:0x%x STATUS:0x%x MCTRL:0x%x\n",
+ why,
+ intr_status,
+ zynq_fpga_read(priv, CTRL_OFFSET),
+ zynq_fpga_read(priv, LOCK_OFFSET),
+ zynq_fpga_read(priv, INT_MASK_OFFSET),
+ zynq_fpga_read(priv, STATUS_OFFSET),
+ zynq_fpga_read(priv, MCTRL_OFFSET));
+out_clk:
clk_disable(priv->clk);
-
out_free:
dma_free_coherent(priv->dev, count, kbuf, dma_addr);
-
return err;
}
@@ -475,7 +482,7 @@ static int zynq_fpga_probe(struct platform_device *pdev)
/* unlock the device */
zynq_fpga_write(priv, UNLOCK_OFFSET, UNLOCK_MASK);
- zynq_fpga_write(priv, INT_MASK_OFFSET, 0xFFFFFFFF);
+ zynq_fpga_set_irq_mask(priv, 0);
zynq_fpga_write(priv, INT_STS_OFFSET, IXR_ALL_MASK);
err = devm_request_irq(dev, priv->irq, zynq_fpga_isr, 0, dev_name(dev),
priv);
--
2.1.4
^ permalink raw reply related
* [PATCH fpga 3/9] fpga zynq: Fix incorrect ISR state on bootup
From: Jason Gunthorpe @ 2016-11-09 22:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478732303-13718-1-git-send-email-jgunthorpe@obsidianresearch.com>
It is best practice to clear and mask all interrupts before
associating the IRQ, and this should be done after the clock
is enabled.
This corrects a bad result from zynq_fpga_ops_state on bootup
where left over latched values in INT_STS_OFFSET caused it to
report an unconfigured FPGA as configured.
After this change the boot up operating state for an unconfigured
FPGA reports 'unknown'.
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
---
drivers/fpga/zynq-fpga.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c
index 86f4377e2b52..40cf0feaca7c 100644
--- a/drivers/fpga/zynq-fpga.c
+++ b/drivers/fpga/zynq-fpga.c
@@ -460,13 +460,6 @@ static int zynq_fpga_probe(struct platform_device *pdev)
return priv->irq;
}
- err = devm_request_irq(dev, priv->irq, zynq_fpga_isr, 0,
- dev_name(dev), priv);
- if (err) {
- dev_err(dev, "unable to request IRQ\n");
- return err;
- }
-
priv->clk = devm_clk_get(dev, "ref_clk");
if (IS_ERR(priv->clk)) {
dev_err(dev, "input clock not found\n");
@@ -482,6 +475,16 @@ static int zynq_fpga_probe(struct platform_device *pdev)
/* unlock the device */
zynq_fpga_write(priv, UNLOCK_OFFSET, UNLOCK_MASK);
+ zynq_fpga_write(priv, INT_MASK_OFFSET, 0xFFFFFFFF);
+ zynq_fpga_write(priv, INT_STS_OFFSET, IXR_ALL_MASK);
+ err = devm_request_irq(dev, priv->irq, zynq_fpga_isr, 0, dev_name(dev),
+ priv);
+ if (err) {
+ dev_err(dev, "unable to request IRQ\n");
+ clk_unprepare(priv->clk);
+ return err;
+ }
+
clk_disable(priv->clk);
err = fpga_mgr_register(dev, "Xilinx Zynq FPGA Manager",
--
2.1.4
^ permalink raw reply related
* [PATCH fpga 2/9] fpga zynq: Check the bitstream for validity
From: Jason Gunthorpe @ 2016-11-09 22:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478732303-13718-1-git-send-email-jgunthorpe@obsidianresearch.com>
There is no sense in sending a bitstream we know will not work, and
with the variety of options for bitstream generation in Xilinx tools
it is not terribly clear or very well documented what the correct
input should be, especially since auto-detection was removed from this
driver.
All Zynq full configuration bitstreams must start with the sync word in
the correct byte order.
Zynq is also only able to DMA dword quantities, so bitstreams must be
a multiple of 4 bytes. This also fixes a DMA-past the end bug.
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
---
drivers/fpga/zynq-fpga.c | 40 +++++++++++++++++++++++++++++++---------
1 file changed, 31 insertions(+), 9 deletions(-)
diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c
index e72340ea7323..86f4377e2b52 100644
--- a/drivers/fpga/zynq-fpga.c
+++ b/drivers/fpga/zynq-fpga.c
@@ -175,6 +175,19 @@ static irqreturn_t zynq_fpga_isr(int irq, void *data)
return IRQ_HANDLED;
}
+/* Sanity check the proposed bitstream. It must start with the sync word in
+ * the correct byte order. The input is a Xilinx .bin file with every 32 bit
+ * quantity swapped.
+ */
+static bool zynq_fpga_has_sync(const char *buf, size_t count)
+{
+ for (; count > 4; buf += 4, count -= 4)
+ if (buf[0] == 0x66 && buf[1] == 0x55 && buf[2] == 0x99 &&
+ buf[3] == 0xaa)
+ return true;
+ return false;
+}
+
static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
const char *buf, size_t count)
{
@@ -184,12 +197,28 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
priv = mgr->priv;
+ /* The hardware can only DMA multiples of 4 bytes, and we need at
+ * least the sync word and something else to do anything.
+ */
+ if (count <= 4 || (count % 4) != 0) {
+ dev_err(priv->dev,
+ "Invalid bitstream size, must be multiples of 4 bytes\n");
+ return -EINVAL;
+ }
+
err = clk_enable(priv->clk);
if (err)
return err;
/* don't globally reset PL if we're doing partial reconfig */
if (!(flags & FPGA_MGR_PARTIAL_RECONFIG)) {
+ if (!zynq_fpga_has_sync(buf, count)) {
+ dev_err(priv->dev,
+ "Invalid bitstream, could not find a sync word. Bitstream must be a byte swaped .bin file\n");
+ err = -EINVAL;
+ goto out_err;
+ }
+
/* assert AXI interface resets */
regmap_write(priv->slcr, SLCR_FPGA_RST_CTRL_OFFSET,
FPGA_RST_ALL_MASK);
@@ -287,12 +316,9 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr,
struct zynq_fpga_priv *priv;
int err;
char *kbuf;
- size_t in_count;
dma_addr_t dma_addr;
- u32 transfer_length;
u32 intr_status;
- in_count = count;
priv = mgr->priv;
kbuf = dma_alloc_coherent(priv->dev, count, &dma_addr, GFP_KERNEL);
@@ -318,11 +344,7 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr,
*/
zynq_fpga_write(priv, DMA_SRC_ADDR_OFFSET, (u32)(dma_addr) + 1);
zynq_fpga_write(priv, DMA_DST_ADDR_OFFSET, (u32)DMA_INVALID_ADDRESS);
-
- /* convert #bytes to #words */
- transfer_length = (count + 3) / 4;
-
- zynq_fpga_write(priv, DMA_SRC_LEN_OFFSET, transfer_length);
+ zynq_fpga_write(priv, DMA_SRC_LEN_OFFSET, count / 4);
zynq_fpga_write(priv, DMA_DEST_LEN_OFFSET, 0);
wait_for_completion(&priv->dma_done);
@@ -338,7 +360,7 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr,
clk_disable(priv->clk);
out_free:
- dma_free_coherent(priv->dev, in_count, kbuf, dma_addr);
+ dma_free_coherent(priv->dev, count, kbuf, dma_addr);
return err;
}
--
2.1.4
^ permalink raw reply related
* [PATCH fpga 1/9] fpga zynq: Add missing \n to messages
From: Jason Gunthorpe @ 2016-11-09 22:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478732303-13718-1-git-send-email-jgunthorpe@obsidianresearch.com>
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
---
drivers/fpga/zynq-fpga.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c
index c2fb4120bd62..e72340ea7323 100644
--- a/drivers/fpga/zynq-fpga.c
+++ b/drivers/fpga/zynq-fpga.c
@@ -217,7 +217,7 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
INIT_POLL_DELAY,
INIT_POLL_TIMEOUT);
if (err) {
- dev_err(priv->dev, "Timeout waiting for PCFG_INIT");
+ dev_err(priv->dev, "Timeout waiting for PCFG_INIT\n");
goto out_err;
}
@@ -231,7 +231,7 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
INIT_POLL_DELAY,
INIT_POLL_TIMEOUT);
if (err) {
- dev_err(priv->dev, "Timeout waiting for !PCFG_INIT");
+ dev_err(priv->dev, "Timeout waiting for !PCFG_INIT\n");
goto out_err;
}
@@ -245,7 +245,7 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
INIT_POLL_DELAY,
INIT_POLL_TIMEOUT);
if (err) {
- dev_err(priv->dev, "Timeout waiting for PCFG_INIT");
+ dev_err(priv->dev, "Timeout waiting for PCFG_INIT\n");
goto out_err;
}
}
@@ -262,7 +262,7 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
/* check that we have room in the command queue */
status = zynq_fpga_read(priv, STATUS_OFFSET);
if (status & STATUS_DMA_Q_F) {
- dev_err(priv->dev, "DMA command queue full");
+ dev_err(priv->dev, "DMA command queue full\n");
err = -EBUSY;
goto out_err;
}
@@ -331,7 +331,7 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr,
zynq_fpga_write(priv, INT_STS_OFFSET, intr_status);
if (!((intr_status & IXR_D_P_DONE_MASK) == IXR_D_P_DONE_MASK)) {
- dev_err(priv->dev, "Error configuring FPGA");
+ dev_err(priv->dev, "Error configuring FPGA\n");
err = -EFAULT;
}
@@ -426,7 +426,7 @@ static int zynq_fpga_probe(struct platform_device *pdev)
priv->slcr = syscon_regmap_lookup_by_phandle(dev->of_node,
"syscon");
if (IS_ERR(priv->slcr)) {
- dev_err(dev, "unable to get zynq-slcr regmap");
+ dev_err(dev, "unable to get zynq-slcr regmap\n");
return PTR_ERR(priv->slcr);
}
@@ -434,26 +434,26 @@ static int zynq_fpga_probe(struct platform_device *pdev)
priv->irq = platform_get_irq(pdev, 0);
if (priv->irq < 0) {
- dev_err(dev, "No IRQ available");
+ dev_err(dev, "No IRQ available\n");
return priv->irq;
}
err = devm_request_irq(dev, priv->irq, zynq_fpga_isr, 0,
dev_name(dev), priv);
if (err) {
- dev_err(dev, "unable to request IRQ");
+ dev_err(dev, "unable to request IRQ\n");
return err;
}
priv->clk = devm_clk_get(dev, "ref_clk");
if (IS_ERR(priv->clk)) {
- dev_err(dev, "input clock not found");
+ dev_err(dev, "input clock not found\n");
return PTR_ERR(priv->clk);
}
err = clk_prepare_enable(priv->clk);
if (err) {
- dev_err(dev, "unable to enable clock");
+ dev_err(dev, "unable to enable clock\n");
return err;
}
@@ -465,7 +465,7 @@ static int zynq_fpga_probe(struct platform_device *pdev)
err = fpga_mgr_register(dev, "Xilinx Zynq FPGA Manager",
&zynq_fpga_ops, priv);
if (err) {
- dev_err(dev, "unable to register FPGA manager");
+ dev_err(dev, "unable to register FPGA manager\n");
clk_unprepare(priv->clk);
return err;
}
--
2.1.4
^ permalink raw reply related
* [PATCH fpga 0/9] Zynq FPGA Manager Improvements
From: Jason Gunthorpe @ 2016-11-09 22:58 UTC (permalink / raw)
To: linux-arm-kernel
This series is all the changes I made while reviewing the Zynq driver.
The first five patches are independent straight forward changes.
The next four patches rework the FPGA manager core code and all drivers to
only use scatter lists for bitfile storage. This is an essential change
looking forward as the high order physical and vmalloc allocations currently
used are simply unreliable and unusable in many cases.
This does not fully fix the request_firmware path, as that needs changes to
the firmware core, but does all the low level work needed in this
subsystem. Zynq sees a significant improvement as it no longer needs large
amounts of physically contiguous DMA coherent memory.
Other users who can use the new sg interface have no limitations, and could
zero-copy DMA directly out of the page cache, for instance.
I do not have socfpga hardware, so those straightfoward changes are untested,
but I have tested the Zynq driver extensively now.
Jason Gunthorpe (9):
fpga zynq: Add missing \n to messages
fpga zynq: Check the bitstream for validity
fpga zynq: Fix incorrect ISR state on bootup
fpga zynq: Check for errors after completing DMA
fpga zynq: Remove priv->dev
fpga: Add scatterlist based write ops to the driver ops
fpga zynq: Use the scatterlist interface
fpga socfpga: Use the scatterlist interface
fpga: Remove support for non-sg drivers
drivers/fpga/fpga-mgr.c | 87 +++++++++++--
drivers/fpga/socfpga.c | 56 ++++++---
drivers/fpga/zynq-fpga.c | 278 ++++++++++++++++++++++++++++++------------
include/linux/fpga/fpga-mgr.h | 14 ++-
4 files changed, 327 insertions(+), 108 deletions(-)
--
2.1.4
^ permalink raw reply
* [PATCH] mfd: qcom-pm8xxx: Clean up PM8XXX namespace
From: Arnd Bergmann @ 2016-11-09 22:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACRpkdZe0VO=ABfbven8mU0FGb=sJNY_tjk2_GpAP30wsiDkvQ@mail.gmail.com>
On Wednesday, November 9, 2016 11:19:34 PM CET Linus Walleij wrote:
> On Wed, Nov 9, 2016 at 4:47 PM, Lee Jones <lee.jones@linaro.org> wrote:
>
> > How many more Acks do we need?
>
> Jacek and one of the ARM SoC people ideally...
>
> Jacek? Arnd/Olof?
>
Acked-by: Arnd Bergmann <arnd@arndb.de>
^ permalink raw reply
* [PATCHv2] PCI: QDF2432 32 bit config space accessors
From: Bjorn Helgaas @ 2016-11-09 22:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKv+Gu82+5oHMeSvcOL1VG4vw-kVnhq4LjCRtLMw4Nmn0rK2CA@mail.gmail.com>
On Wed, Nov 09, 2016 at 08:29:23PM +0000, Ard Biesheuvel wrote:
> Hi Bjorn,
>
> On 9 November 2016 at 20:06, Bjorn Helgaas <helgaas@kernel.org> wrote:
> > On Wed, Nov 09, 2016 at 02:25:56PM -0500, Christopher Covington wrote:
> >> Hi Bjorn,
> >>
> [...]
> >>
> >> We're working to add the PNP0C02 resource to future firmware, but it's
> >> not in the current firmware. Are dmesg and /proc/iomem from the
> >> current firmware interesting or should we wait for the update to file?
> >
> > Note that the ECAM space is not the only thing that should be
> > described via these PNP0C02 devices. *All* non-enumerable resources
> > should be described by the _CRS method of some ACPI device. Here's a
> > sample from my laptop:
> >
> > PCI: MMCONFIG for domain 0000 [bus 00-3f] at [mem 0xf8000000-0xfbffffff] (base 0xf8000000)
> > system 00:01: [io 0x1800-0x189f] could not be reserved
> > system 00:01: [io 0x0800-0x087f] has been reserved
> > system 00:01: [io 0x0880-0x08ff] has been reserved
> > system 00:01: [io 0x0900-0x097f] has been reserved
> > system 00:01: [io 0x0980-0x09ff] has been reserved
> > system 00:01: [io 0x0a00-0x0a7f] has been reserved
> > system 00:01: [io 0x0a80-0x0aff] has been reserved
> > system 00:01: [io 0x0b00-0x0b7f] has been reserved
> > system 00:01: [io 0x0b80-0x0bff] has been reserved
> > system 00:01: [io 0x15e0-0x15ef] has been reserved
> > system 00:01: [io 0x1600-0x167f] has been reserved
> > system 00:01: [io 0x1640-0x165f] has been reserved
> > system 00:01: [mem 0xf8000000-0xfbffffff] could not be reserved
> > system 00:01: [mem 0xfed10000-0xfed13fff] has been reserved
> > system 00:01: [mem 0xfed18000-0xfed18fff] has been reserved
> > system 00:01: [mem 0xfed19000-0xfed19fff] has been reserved
> > system 00:01: [mem 0xfeb00000-0xfebfffff] has been reserved
> > system 00:01: [mem 0xfed20000-0xfed3ffff] has been reserved
> > system 00:01: [mem 0xfed90000-0xfed93fff] has been reserved
> > system 00:01: [mem 0xf7fe0000-0xf7ffffff] has been reserved
> > system 00:01: Plug and Play ACPI device, IDs PNP0c02 (active)
> >
> > Do you have firmware in the field that may not get updated? If so,
> > I'd like to see the whole solution for that firmware, including the
> > MCFG quirk (which tells the PCI core where the ECAM region is) and
> > whatever PNP0C02 quirk you figure out to actually reserve the region.
> >
> > I proposed a PNP0C02 quirk to Duc along these lines of the below. I
> > don't actually know if it's feasible, but it didn't look as bad as I
> > expected, so I'd kind of like somebody to try it out. I think you
> > would have to call this via a DMI hook (do you have DMI on arm64?),
> > maybe from pnp_init() or similar.
>
> We do have SMBIOS/DMI on arm64, but we have been successful so far not
> to rely on it for quirks, and we'd very much like to keep it that way.
>
> Since this ACPI _CRS method has nothing to do with SMBIOS/DMI, surely
> there is a better way to wire up the reservation code to the
> information exposed by ACPI?
I'm open to other ways, feel free to propose one :)
If you do a quirk, you need some way to identify the machine/firmware
combination, because you don't want to apply the quirk on every
machine. You're trying to work around a firmware issue, so you
probably want something tied to the firmware version. On x86, that's
typically done with DMI.
Bjorn
^ permalink raw reply
* [PATCH] ARM: dts: am335x-baltos: don't reset gpio3 block
From: Tony Lindgren @ 2016-11-09 22:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478077696-21003-1-git-send-email-yegorslists@googlemail.com>
* yegorslists at googlemail.com <yegorslists@googlemail.com> [161102 02:08]:
> From: Yegor Yefremov <yegorslists@googlemail.com>
>
> This change is needed in order to enable some hardware components
> from bootloader.
>
> Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
> ---
> arch/arm/boot/dts/am335x-baltos.dtsi | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/arch/arm/boot/dts/am335x-baltos.dtsi b/arch/arm/boot/dts/am335x-baltos.dtsi
> index dd45d17..09b9541 100644
> --- a/arch/arm/boot/dts/am335x-baltos.dtsi
> +++ b/arch/arm/boot/dts/am335x-baltos.dtsi
> @@ -406,3 +406,7 @@
> &gpio0 {
> ti,no-reset-on-init;
> };
> +
> +&gpio3 {
> + ti,no-reset-on-init;
> +};
Applying into omap-for-v4.10/dt thanks.
Tony
^ permalink raw reply
* [PATCH] ARM: dts: am335x-baltos-ir5221: use both musb channels in host mode
From: Tony Lindgren @ 2016-11-09 22:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476860943-30994-1-git-send-email-yegorslists@googlemail.com>
* yegorslists at googlemail.com <yegorslists@googlemail.com> [161019 00:10]:
> From: Yegor Yefremov <yegorslists@googlemail.com>
>
> Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
> ---
> arch/arm/boot/dts/am335x-baltos-ir5221.dts | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/am335x-baltos-ir5221.dts b/arch/arm/boot/dts/am335x-baltos-ir5221.dts
> index d0faa7b..f599350 100644
> --- a/arch/arm/boot/dts/am335x-baltos-ir5221.dts
> +++ b/arch/arm/boot/dts/am335x-baltos-ir5221.dts
> @@ -114,7 +114,7 @@
>
> &usb1 {
> status = "okay";
> - dr_mode = "otg";
> + dr_mode = "host";
> };
>
> &cpsw_emac0 {
Applying into omap-for-v4.10/dt thanks.
Tony
^ permalink raw reply
* ARM: AMx3xx/DRA7: crypto IP support data
From: Tony Lindgren @ 2016-11-09 22:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476777327-700-1-git-send-email-t-kristo@ti.com>
* Tero Kristo <t-kristo@ti.com> [161018 00:56]:
> Hi,
>
> This series finalizes the crypto support for amx3xx / dra7 socs,
> adding the hwmod data and fixing one issue with l4sec clockdomain
> on dra7.
Applying all into omap-for-v4.10/soc thanks.
Tony
^ permalink raw reply
* Summary of LPC guest MSI discussion in Santa Fe
From: Will Deacon @ 2016-11-09 22:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161109151709.74927f83@t450s.home>
On Wed, Nov 09, 2016 at 03:17:09PM -0700, Alex Williamson wrote:
> On Wed, 9 Nov 2016 20:31:45 +0000
> Will Deacon <will.deacon@arm.com> wrote:
> > On Wed, Nov 09, 2016 at 08:23:03PM +0100, Christoffer Dall wrote:
> > >
> > > (I suppose it's technically possible to get around this issue by letting
> > > QEMU place RAM wherever it wants but tell the guest to never use a
> > > particular subset of its RAM for DMA, because that would conflict with
> > > the doorbell IOVA or be seen as p2p transactions. But I think we all
> > > probably agree that it's a disgusting idea.)
> >
> > Disgusting, yes, but Ben's idea of hotplugging on the host controller with
> > firmware tables describing the reserved regions is something that we could
> > do in the distant future. In the meantime, I don't think that VFIO should
> > explicitly reject overlapping mappings if userspace asks for them.
>
> I'm confused by the last sentence here, rejecting user mappings that
> overlap reserved ranges, such as MSI doorbell pages, is exactly how
> we'd reject hot-adding a device when we meet such a conflict. If we
> don't reject such a mapping, we're knowingly creating a situation that
> potentially leads to data loss. Minimally, QEMU would need to know
> about the reserved region, map around it through VFIO, and take
> responsibility (somehow) for making sure that region is never used for
> DMA. Thanks,
Yes, but my point is that it should be up to QEMU to abort the hotplug, not
the host kernel, since there may be ways in which a guest can tolerate the
overlapping region (e.g. by avoiding that range of memory for DMA).
Will
^ permalink raw reply
* [PATCH v3 3/4] ARM: dts: am33xx: add DMA properties for tscadc
From: Tony Lindgren @ 2016-11-09 22:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1a339132-9dd9-6f29-dd66-3125f0e90555@kernel.org>
* Jonathan Cameron <jic23@kernel.org> [161105 10:35]:
> On 05/10/16 10:04, Mugunthan V N wrote:
> > Add DMA properties for tscadc
> >
> > Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
> The support in the driver is now working it's way through iio.git towards
> linux-next. I'm guessing this and the next patch will ultimately go through
> arm-soc.
>
> Shout if you'd rather I took them through the iio tree.
Applying the dts related patches 3 and 4 into omap-for-v4.10/dt thanks.
Tony
^ permalink raw reply
* [PATCH 1/6] dt-bindings: mdio-mux: Add documentation for mdio mux for NSP SoC
From: Scott Branden @ 2016-11-09 22:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478683994-12008-2-git-send-email-yendapally.reddy@broadcom.com>
One change
On 16-11-09 01:33 AM, Yendapally Reddy Dhananjaya Reddy wrote:
> Add documentation for mdio mux available in Broadcom NSP SoC
>
> Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com>
> ---
> .../devicetree/bindings/net/brcm,mdio-mux-nsp.txt | 57 ++++++++++++++++++++++
> 1 file changed, 57 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/net/brcm,mdio-mux-nsp.txt
>
> diff --git a/Documentation/devicetree/bindings/net/brcm,mdio-mux-nsp.txt b/Documentation/devicetree/bindings/net/brcm,mdio-mux-nsp.txt
> new file mode 100644
> index 0000000..b749a2b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/brcm,mdio-mux-nsp.txt
> @@ -0,0 +1,57 @@
> +Properties for an MDIO bus multiplexer available in Broadcom NSP SoC.
> +
> +This MDIO bus multiplexer defines buses that could access the internal
> +phys as well as external to SoCs. When child bus is selected, one needs
> +to select the below properties to generate desired MDIO transaction on
> +appropriate bus.
> +
> +Required properties in addition to the generic multiplexer properties:
> +
> +MDIO multiplexer node:
> +- compatible: brcm,mdio-mux-iproc.
This should be brcm,mdio-mux-nsp
> +- reg: Should contain registers location and length.
> +- reg-names: Should contain the resource reg names.
> + - bus-ctrl: mdio bus control register address space required to
> + select the bus master. This property is not required for SoC's
> + that doesn't provide master selection.
> + - mgmt-ctrl: mdio management control register address space
> +
> +Sub-nodes:
> + Each bus master should be represented as a sub-node.
> +
> +Sub-nodes required properties:
> +- reg: Bus master number. Should be 0x10 to access the external mdio devices.
> +- address-cells: should be 1
> +- size-cells: should be 0
> +
> +Every non-ethernet PHY requires a compatible property so that it could be
> +probed based on this compatible string.
> +
> +Additional information regarding generic multiplexer properties can be found
> +at- Documentation/devicetree/bindings/net/mdio-mux.txt
> +
> +example:
> +
> + mdio_mux: mdio-mux at 3f190 {
> + compatible = "brcm,mdio-mux-nsp";
> + reg = <0x3f190 0x4>,
> + <0x32000 0x4>;
> + reg-names = "bus-ctrl", "mgmt-ctrl";
> + mdio-parent-bus = <&mdio>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + mdio at 0 {
> + reg = <0x0>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + usb3_phy: usb3-phy at 10 {
> + compatible = "brcm,nsp-usb3-phy";
> + reg = <0x10>;
> + usb3-ctrl-syscon = <&usb3_ctrl>;
> + #phy-cells = <0>;
> + status = "disabled";
> + };
> + };
> + };
>
^ permalink raw reply
* [PATCH] mfd: qcom-pm8xxx: Clean up PM8XXX namespace
From: Linus Walleij @ 2016-11-09 22:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161109154727.GG13127@dell>
On Wed, Nov 9, 2016 at 4:47 PM, Lee Jones <lee.jones@linaro.org> wrote:
> How many more Acks do we need?
Jacek and one of the ARM SoC people ideally...
Jacek? Arnd/Olof?
Yours,
Linus Walleij
^ permalink raw reply
* Summary of LPC guest MSI discussion in Santa Fe
From: Alex Williamson @ 2016-11-09 22:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161109203145.GO17771@arm.com>
On Wed, 9 Nov 2016 20:31:45 +0000
Will Deacon <will.deacon@arm.com> wrote:
> On Wed, Nov 09, 2016 at 08:23:03PM +0100, Christoffer Dall wrote:
> >
> > (I suppose it's technically possible to get around this issue by letting
> > QEMU place RAM wherever it wants but tell the guest to never use a
> > particular subset of its RAM for DMA, because that would conflict with
> > the doorbell IOVA or be seen as p2p transactions. But I think we all
> > probably agree that it's a disgusting idea.)
>
> Disgusting, yes, but Ben's idea of hotplugging on the host controller with
> firmware tables describing the reserved regions is something that we could
> do in the distant future. In the meantime, I don't think that VFIO should
> explicitly reject overlapping mappings if userspace asks for them.
I'm confused by the last sentence here, rejecting user mappings that
overlap reserved ranges, such as MSI doorbell pages, is exactly how
we'd reject hot-adding a device when we meet such a conflict. If we
don't reject such a mapping, we're knowingly creating a situation that
potentially leads to data loss. Minimally, QEMU would need to know
about the reserved region, map around it through VFIO, and take
responsibility (somehow) for making sure that region is never used for
DMA. Thanks,
Alex
^ permalink raw reply
* [PATCH RFC 00/12] tda998x updates
From: Russell King - ARM Linux @ 2016-11-09 22:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478691905.2835.12.camel@linaro.org>
On Wed, Nov 09, 2016 at 11:45:05AM +0000, Jon Medhurst (Tixy) wrote:
> On Tue, 2016-11-08 at 18:24 +0000, Russell King - ARM Linux wrote:
> > On Tue, Nov 08, 2016 at 05:20:36PM +0000, Jon Medhurst (Tixy) wrote:
> > > On Tue, 2016-11-08 at 13:34 +0000, Russell King - ARM Linux wrote:
> > > > On Tue, Nov 08, 2016 at 01:32:15PM +0000, Russell King - ARM Linux wrote:
> > > > > Unfortunately, my drm-tda998x-devel branch is slightly out of date with
> > > > > these patches it's the original set of 10 patches. I've not pushed
> > > > > these ones out to that branch yet, as I've three additional patches on
> > > > > top of these which aren't "ready" for pushing out.
> > > >
> > > > Here's the delta between the branch and what I just posted:
> > > >
> > > > diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
> > > [...]
> > >
> > > I have a working setup for HDMI audio on Juno an would like to test this
> > > series but am struggling to work out which patches to apply in what
> > > order to what branch, can you be specific? (I've tried various
> > > combinations of patches series from the list, drm-tda998x-devel, and the
> > > diff you posted)
> >
> > Hmm, I guess this is going to be annoyingly rather difficult then.
> > The structure of my git tree is:
> >
> > v4.8 ---------------- mali patch ------------------ merge --- these patches
> > v4.7 -- tda998x audio patches (up to df0bd1e8f3c5) --^
> >
> > which makes it rather difficult to send out a series that people can
> > apply as patches without first replicating that merge. I guess the
> > answer is... use the _patches_ for review, and I'll push out the
> > changes into drm-tda998x-devel... should be there soon. Look for
> > commit hash d61fa2e50f2a. (Bah, slow 'net connections.)
>
> Testing gets more complicated as I'm using 4.9-rc? which has a DMA fix
> needed for audio [1] and breaks hdmi-codec which I hope I fixed [2].
Well, ultimately it's going to be merged during the 4.10 merge window,
so it's going to be combined with lots of other changes along the way.
I'm testing it against 4.8 on the Dove Cubox, and build testing it
against 4.9-rc, so it's good someone is hardware testing with 4.9-rc
merged.
> Anyway, I merged in drm-tda998x-devel and audio continued to work on my
> HDMI connected monitor. So I guess that's
>
> Tested-by: Jon Medhurst <tixy@linaro.org>
Thanks.
> I also reviewed the patches in this series. They look like a mostly
> mechanical code organisation improvement, and whilst I'm not very
> familiar with the driver and DRM, the other actual code changes look OK
> too. So, FWIW:
Yes, much of it is a code reorganisation, its mainly preparation for
converting the driver to be DRM bridge based, but in reviewing the
initial DRM bridge conversion patch, I spotted some weaknesses in the
existing code which the first few patches of this series address. I
don't think they're serious enough to warrant submission into -rc
though.
The next three patches I'll post in the coming days (once I've finished
evaluating one of them) should reduce power consumption of the device
by shutting down some blocks we never use, and some preparation to
support CEC (I've had CEC working with Hans Verkil's patches for some
time now, I'm mostly waiting for the CEC core to move out of staging,
at which point it can end up in a saner place other than
drivers/gpu/drm/i2c.)
> Acked-by: Jon Medhurst <tixy@linaro.org>
Thanks, and thanks for testing.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
^ permalink raw reply
* ACPI namespace details for ARM64
From: Bjorn Helgaas @ 2016-11-09 22:05 UTC (permalink / raw)
To: linux-arm-kernel
Hi all,
We've been working through the details of getting ACPI to work on
arm64, and there have been lots of questions about what this means for
PCI. I've outlined this for several people individually, but I'm
going to send this separately, apart from a specific patch series, to
make sure we're all on the same page. Please correct my errors and
misunderstandings.
Bjorn
The basic requirement is that the ACPI namespace should describe
*everything* that consumes address space unless there's another
standard way for the OS to find it [1, 2]. ?For example, windows that
are forwarded to PCI by a PCI host bridge should be described via ACPI
devices, since the OS can't locate the host bridge by itself. ?PCI
devices *below* the host bridge do not need to be described via ACPI,
because the resources they consume are inside the host bridge windows,
and the OS can discover them via the standard PCI enumeration
mechanism (using config accesses to read and size the BARs).
This ACPI resource description is done via _CRS methods of devices in
the ACPI namespace [2]. ? _CRS methods are like generalized PCI BARs:
the OS can read _CRS and figure out what resource is being consumed
even if it doesn't have a driver for the device [3]. ?That's important
because it means an old OS can work correctly even on a system with
new devices unknown to the OS. ?The new devices won't do anything, but
the OS can at least make sure no resources conflict with them.
Static tables like MCFG, HPET, ECDT, etc., are *not* mechanisms for
reserving address space! The static tables are for things the OS
needs to know early in boot, before it can parse the ACPI namespace.
If a new table is defined, an old OS needs to operate correctly even
though it ignores the table. _CRS allows that because it is generic
and understood by the old OS; a static table does not.
If the OS is expected to manage an ACPI device, that device will have
a specific _HID/_CID that tells the OS what driver to bind to it, and
the _CRS tells the OS and the driver where the device's registers are.
PNP0C02 "motherboard" devices are basically a catch-all. ?There's no
programming model for them other than "don't use these resources for
anything else." ?So any address space that is (1) not claimed by some
other ACPI device and (2) should not be assigned by the OS to
something else, should be claimed by a PNP0C02 _CRS method.
PCI host bridges are PNP0A03 or PNP0A08 devices. ?Their _CRS should
describe all the address space they consume. ?In principle, this would
be all the windows they forward down to the PCI bus, as well as the
bridge registers themselves. ?The bridge registers include things like
secondary/subordinate bus registers that determine the bus range below
the bridge, window registers that describe the apertures, etc. ?These
are all device-specific, non-architected things, so the only way a
PNP0A03/PNP0A08 driver can manage them is via _PRS/_CRS/_SRS, which
contain the device-specific details. ?These bridge registers also
include ECAM space, since it is consumed by the bridge.
ACPI defined a Producer/Consumer bit that was intended to distinguish
the bridge apertures from the bridge registers [4, 5]. ?However,
BIOSes didn't use that bit correctly, and the result is that OSes have
to assume that everything in a PCI host bridge _CRS is a window. ?That
leaves no way to describe the bridge registers in the PNP0A03/PNP0A08
device itself.
The workaround is to describe the bridge registers (including ECAM
space) in PNP0C02 catch-all devices [6]. ?With the exception of ECAM,
the bridge register space is device-specific anyway, so the generic
PNP0A03/PNP0A08 driver (pci_root.c) has no need to know about it. ?For
ECAM, pci_root.c learns about the space from either MCFG or the _CBA
method.
Note that the PCIe spec actually does require ECAM unless there's a
standard firmware interface for config access, e.g., the ia64 SAL
interface [7]. One reason is that we want a generic host bridge
driver (pci_root.c), and a generic driver requires a generic way to
access config space.
[1] ACPI 6.0, sec 6.1:
For any device that is on a non-enumerable type of bus (for
example, an ISA bus), OSPM enumerates the devices' identifier(s)
and the ACPI system firmware must supply an _HID object ... for
each device to enable OSPM to do that.
[2] ACPI 6.0, sec 3.7:
The OS enumerates motherboard devices simply by reading through
the ACPI Namespace looking for devices with hardware IDs.
Each device enumerated by ACPI includes ACPI-defined objects in
the ACPI Namespace that report the hardware resources the device
could occupy [_PRS], an object that reports the resources that are
currently used by the device [_CRS], and objects for configuring
those resources [_SRS]. The information is used by the Plug and
Play OS (OSPM) to configure the devices.
[3] ACPI 6.0, sec 6.2:
OSPM uses device configuration objects to configure hardware
resources for devices enumerated via ACPI. Device configuration
objects provide information about current and possible resource
requirements, the relationship between shared resources, and
methods for configuring hardware resources.
When OSPM enumerates a device, it calls _PRS to determine the
resource requirements of the device. It may also call _CRS to
find the current resource settings for the device. Using this
information, the Plug and Play system determines what resources
the device should consume and sets those resources by calling the
device?s _SRS control method.
In ACPI, devices can consume resources (for example, legacy
keyboards), provide resources (for example, a proprietary PCI
bridge), or do both. Unless otherwise specified, resources for a
device are assumed to be taken from the nearest matching resource
above the device in the device hierarchy.
[4] ACPI 6.0, sec 6.4.3.5.4:
Extended Address Space Descriptor
General Flags: Bit [0] Consumer/Producer:
1?This device consumes this resource
0?This device produces and consumes this resource
[5] ACPI 6.0, sec 19.6.43:
ResourceUsage specifies whether the Memory range is consumed by
this device (ResourceConsumer) or passed on to child devices
(ResourceProducer). If nothing is specified, then
ResourceConsumer is assumed.
[6] PCI Firmware 3.0, sec 4.1.2:
If the operating system does not natively comprehend reserving the
MMCFG region, the MMCFG region must be reserved by firmware. The
address range reported in the MCFG table or by _CBA method (see
Section 4.1.3) must be reserved by declaring a motherboard
resource. For most systems, the motherboard resource would appear
at the root of the ACPI namespace (under \_SB) in a node with a
_HID of EISAID (PNP0C02), and the resources in this case should
not be claimed in the root PCI bus?s _CRS. The resources can
optionally be returned in Int15 E820 or EFIGetMemoryMap as
reserved memory but must always be reported through ACPI as a
motherboard resource.
[7] PCI Express 3.0, sec 7.2.2:
For systems that are PC-compatible, or that do not implement a
processor-architecture-specific firmware interface standard that
allows access to the Configuration Space, the ECAM is required as
defined in this section.
^ permalink raw reply
* [PATCH v2 4/9] regulator: lp873x: Add support for populating input supply
From: Tony Lindgren @ 2016-11-09 21:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161109182618.ajqhtffure76zfnf@rob-hp-laptop>
* Rob Herring <robh@kernel.org> [161109 11:26]:
> On Wed, Nov 02, 2016 at 10:58:40AM +0530, Lokesh Vutla wrote:
> > On Monday 31 October 2016 02:11 AM, Rob Herring wrote:
> > > On Fri, Oct 21, 2016 at 04:08:36PM +0530, Lokesh Vutla wrote:
> > >> In order to have a proper topology of regulators for a platform, each
> > >> registering regulator needs to populate supply_name field for identifying
> > >> its supply's name. Add supply_name field for lp873x regulators.
> > >>
> > >> Cc: Lee Jones <lee.jones@linaro.org>
> > >> Cc: Keerthy <j-keerthy@ti.com>
> > >> Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
> > >> ---
> > >> Documentation/devicetree/bindings/mfd/lp873x.txt | 8 ++++++++
> > >> drivers/regulator/lp873x-regulator.c | 1 +
...
> Acked-by: Rob Herring <robh@kernel.org>
Please send this patch separately to the regulator maintainer.
Thanks,
Tony
^ permalink raw reply
* [PATCH v2 0/5] ARM: OMAP: dead code removal
From: Tony Lindgren @ 2016-11-09 21:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478268138-7044-1-git-send-email-Nicolae_Rosia@mentor.com>
* Nicolae Rosia <Nicolae_Rosia@mentor.com> [161104 07:02]:
> Hi,
>
> I have identified some dead code which can be removed.
>
> v2:
> - Added details on each commit on how the code ended up unused.
>
> Nicolae Rosia (5):
> ARM: OMAP4: kill omap4_pmic_init and omap4_pmic_get_config
> ARM: OMAP3: kill omap3_pmic_get_config and twl_{get,set}_voltage
> ARM: OMAP3: kill omap3_pmic_init
> ARM: OMAP2: kill omap2_pmic_init
> ARM: OMAP: kill omap_pmic_init
>
> arch/arm/mach-omap2/twl-common.c | 483 ---------------------------------------
> arch/arm/mach-omap2/twl-common.h | 24 --
> 2 files changed, 507 deletions(-)
Thanks applying all these into omap-for-v4.10/legacy.
Regards,
Tony
^ permalink raw reply
* [PATCH v1 03/11] drivers: soc: hisi: Add support for Hisilicon Djtag driver
From: Arnd Bergmann @ 2016-11-09 21:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5822A5F6.9040806@gmail.com>
On Wednesday, November 9, 2016 9:58:38 AM CET Anurup M wrote:
>
> > I also see that the compatible strings have the version included in
> > them, and you can probably drop them by requiring them only in the
> > fallback:
> >
> > compatible = "hisilicon,hip05-cpu-djtag", "hisilicon,djtag-v1";
> > compatible = "hisilicon,hip05-io-djtag", "hisilicon,djtag-v1";
> > compatible = "hisilicon,hip06-cpu-djtag", "hisilicon,djtag-v1";
> > compatible = "hisilicon,hip06-io-djtag", "hisilicon,djtag-v2";
> > compatible = "hisilicon,hip07-cpu-djtag", "hisilicon,djtag-v2";
> > compatible = "hisilicon,hip07-io-djtag", "hisilicon,djtag-v2";
> >
> > We want to have the first entry be as specific as possible, but
> > the last (second) entry is the one that can be used by the driver
> > for matching. When a future hip08/hip09/... chip uses an existing
> > interface, you then don't have to update the driver.
> Thanks. I had a similar thought on this. So as I have the version string
> in the
> second entry "-v(1/2)".
> I can use it in driver for matching. So i think I will change it as below.
> Please correct me if my understanding is wrong.
>
> static const struct of_device_id djtag_of_match[] = {
> - /* for hip05(D02) cpu die */
> - { .compatible = "hisilicon,hip05-cpu-djtag-v1",
> + /* for hisi djtag-v1 cpu die */
> + { .compatible = "hisilicon,hisi-cpu-djtag-v1",
> .data = djtag_readwrite_v1 },
> - /* for hip05(D02) io die */
> - { .compatible = "hisilicon,hip05-io-djtag-v1",
> + /* for hisi djtag-v1 io die */
> + { .compatible = "hisilicon,hisi-io-djtag-v1",
>From the code it looks like "hisilicon,hisi-io-djtag-v1" and
"hisilicon,hisi-cpu-djtag-v1" have the same register-level interface,
so we just need one compatible string for them to match the driver.
Arnd
^ permalink raw reply
* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
From: Arnd Bergmann @ 2016-11-09 21:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161109135453.2e5402bd@lxorguk.ukuu.org.uk>
On Wednesday, November 9, 2016 1:54:53 PM CET One Thousand Gnomes wrote:
> > I think it is a relatively safe assumption that there is only one
> > ISA bridge. A lot of old drivers hardcode PIO or memory addresses
>
> It's not a safe assumption for x86 at least. There are a few systems with
> multiple ISA busses particularly older laptops with a docking station.
But do they have multiple ISA domains? There is no real harm in supporting
it, the (small) downsides I can think of are:
- a few extra cycles for the lookup, from possibly walking a linked list
to find the correct set of helpers and MMIO addresses
- making it too general could invite more people to design hardware
around the infrastructure when we really want them to stop adding
stuff like this.
Arnd
^ permalink raw reply
* [PATCH v2 0/8] Support TPS65217 PMIC interrupt in DT
From: Tony Lindgren @ 2016-11-09 21:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161028123702.21849-1-woogyom.kim@gmail.com>
* Milo Kim <woogyom.kim@gmail.com> [161028 05:38]:
> TPS65217 interrupt events include push button pressed/released, USB and AC
> voltage status change. AM335x bone based boards (like BB, BBB, BBG) have
> common PMIC interrupt pin (named NMI) of AM335x core.
>
> This patchset support interrupts in device tree file.
Applying into omap-for-v4.10/dt except the last patch I'll apply into
omap-for-v4.10/fixes-not-urgent.
Regards,
Tony
^ 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